日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

2017.10.3北京清北综合强化班DAY3

發布時間:2025/3/14 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 2017.10.3北京清北综合强化班DAY3 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

括號序列(bracket)

Time Limit:1000ms?? Memory Limit:128MB

?

題目描述

LYK有一個括號序列,但這個序列不一定合法。

一個合法的括號序列如下:

()是合法的括號序列。

若A是合法的括號序列,則(A)是合法的括號序列。

若A和B分別是合法的括號序列,則AB是合法的括號序列。

LYK想通過盡可能少的操作將這個不一定合法的括號序列變成合法的括號序列。一次修改操作是將某個字符變成另一個字符。

你能幫幫它嗎?

?

輸入格式(bracket.in)

??? 一行一個字符串S。

?

輸出格式(bracket.out)

??? 一個數表示最少修改次數。

?

輸入樣例

()))

?

輸出樣例

1

?

樣例解釋

將第二個字符修改成(即可。

?

數據范圍

對于30%的數據|S|<=10。

對于60%的數據|S|<=1000。

對于100%的數據|S|<=100000。且|S|是偶數。

?

題解:貪心

遇到右括號,如果之前有左括號就抵消 否則 step++,把它變成左括號

最后剩下一堆左括號,之前step+左括號個數/2 即可。

本萌妹的AC代碼真好看..

#include<iostream> #include<cstdio> #include<cstring> using namespace std;string s; int len,top,ans;int main(){freopen("bracket.in","r",stdin);freopen("bracket.out","w",stdout);cin>>s;len=s.length();for(int i=0;i<len;i++){if(s[i]=='(')top++;if(s[i]==')'){if(top)top--;else ans++,top++;}}printf("%d\n",ans+top/2);fclose(stdin);fclose(stdout);return 0; } AC

?

公交車(bus)

Time Limit:1000ms?? Memory Limit:128MB

?

題目描述

LYK在玩一個游戲。

有k群小怪獸想乘坐公交車。第i群小怪獸想從xi出發乘坐公交車到yi。但公交車的容量只有M,而且這輛公交車只會從1號點行駛到n號點。

LYK想讓小怪獸們盡可能的到達自己想去的地方。它想知道最多能滿足多少小怪獸的要求。

當然一群小怪獸沒必要一起上下車,它們是可以被分開來的。

?

輸入格式(bus.in)

??? 第一行三個數k,n,M。

??? 接下來k行每行3個數xi,yi和ci。其中ci表示第i群小怪獸的小怪獸數量。

?

輸出格式(bus.out)

??? 一個數表示最多有多少只小怪獸能滿足要求。

?

輸入樣例

3 5 3

1 3 4

3 5 2

1 5 3

?

輸出樣例

5

?

樣例解釋

第一群的3只小怪獸在1號點上車,并在3號點下車。

第二群的2只小怪獸在3號點上車,5號點下車。

?

數據范圍

對于30%的數據小怪獸的總數不超過10只,n<=10。

對于另外30%的數據k,n<=1000。

對于100%的數據1<=n<=20000,1<=k<=50000,1<=M<=100,1<=ci<=100,1<=xi<yi<=n。

?

題解:

#include<iostream> #include<algorithm> #include<cstdio> #include<cstring>using namespace std;int k,n,m,ans; int c[2017]; struct GS{int x,y,c; }gs[50002];bool cmp(GS a,GS b){return a.y-a.x<b.y-b.x; }void dfs(int x,int sum){if(x==k+1){ans=max(ans,sum);return;}int maxx=-1;for(int i=gs[x].x;i<gs[x].y;i++)maxx=max(maxx,c[i]);int gg=min(gs[x].c,m-maxx);for(int i=gs[x].x;i<gs[x].y;i++)c[i]+=gg;dfs(x+1,sum+gg);for(int i=gs[x].x;i<gs[x].y;i++)c[i]-=gg;dfs(x+1,sum); }int main(){freopen("bus.in","r",stdin);freopen("bus.out","w",stdout);scanf("%d%d%d",&k,&n,&m);//k群小怪獸,n個站,容量mfor(int i=1;i<=k;i++)scanf("%d%d%d",&gs[i].x,&gs[i].y,&gs[i].c);if(k<=30){dfs(1,0); printf("%d\n",ans);fclose(stdin);fclose(stdout);return 0;}sort(gs+1,gs+k+1,cmp);for(int i=1;i<=k;i++){int l=gs[i].x,r=gs[i].y;int maxx=-1;for(int h=l;h<r;h++)maxx=max(maxx,c[i]);int gg=min(gs[i].c,m-maxx);ans+=gg;for(int h=l;h<r;h++)c[i]+=gg;}printf("%d\n",ans);fclose(stdin);fclose(stdout);return 0; } 玄學貪心20

首先看這么一個經典問題,尋找盡量多的互不相交的區間。

做法是,按照右端點從小到大排序,不需要管左端點。

?

選擇第一條線段,然后第3.4條。那么假設我們不選第一條線段,選擇第二條,是否會

更優呢?我們發現第二條線段比第一條凸出一部分,這就導致再選擇下一條線段時對于左

端點的要求更高。也就是必須要左端點更靠右。那么對于本題,線段有了權值。對于一群

小怪獸來說,到底是上1只,還是2只,還是全上,還是一個都不上呢?

?

假設現在公交車的容積為3,假設對于第1群怪獸為線段1,有3只怪獸

我只讓2只怪獸上車,那么還有一個空座,讓第二群怪獸上來一個

為線段2,圖上標注好了上下車距離。那么看出第一群怪獸到底是全上

還是上2個,第二群上一個呢。發現,第一群怪獸全上是更優的,因為

同樣是運3只怪獸,如果第1群上2個,第2群比第一群的路線凸出來很多,

占更多的座位。好了,到目前為止貪心的策略為能上就上。

設f[i]為第i個點對于第P群怪獸,看看這一群能上幾只怪獸,就要求出

這群怪獸的行程的起點到終點的一段區間內的最大值。然后計算最多

能上幾只怪獸。然后修改f數組。發現這是一個區間求最大值,區間修改

的操作,線段樹可以維護。

?

#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #define maxn 200005 using namespace std;int k,n,m,ans; struct Tree{int l,r,sum,s; }tr[maxn<<2]; struct GS{int x,y,c;bool operator < (const GS &a) const{return y<a.y;} }a[maxn*3];void pushup(int rt){tr[rt].sum=max(tr[rt<<1].sum,tr[rt<<1|1].sum);return; }void pushdown(int rt){if(!tr[rt].s)return;tr[rt<<1].s+=tr[rt].s;tr[rt<<1|1].s+=tr[rt].s;tr[rt<<1].sum+=tr[rt].s;tr[rt<<1|1].sum+=tr[rt].s;tr[rt].s=0; }void build(int rt,int l,int r){tr[rt].l=l;tr[rt].r=r;if(l==r)return;int mid=(l+r)>>1;build(rt<<1,l,mid);build(rt<<1|1,mid+1,r); }int query(int rt,int l,int r,int qx,int qy){pushdown(rt);if(l>=qx&&r<=qy){return tr[rt].sum;}int mid=(l+r)>>1;if(qy<=mid)return query(rt<<1,l,mid,qx,qy);else if(qx>mid)return query(rt<<1|1,mid+1,r,qx,qy);else return max(query(rt<<1,l,mid,qx,mid),query(rt<<1|1,mid+1,r,mid+1,qy)); }void change(int rt,int l,int r,int qx,int qy,int z){pushdown(rt);if(l>=qx&&r<=qy){tr[rt].sum+=z;tr[rt].s+=z;return;}int mid=(l+r)>>1;if(qy<=mid)change(rt<<1,l,mid,qx,qy,z);else if(qx>mid)change(rt<<1|1,mid+1,r,qx,qy,z);else change(rt<<1,l,mid,qx,mid,z),change(rt<<1|1,mid+1,r,mid+1,qy,z);pushup(rt); }int main(){scanf("%d%d%d",&k,&n,&m);for(int i=1;i<=k;i++)scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].c);sort(a+1,a+k+1);for(int i=1;i<=k;i++){int p=min(a[i].c,m-query(1,1,n,a[i].x,a[i].y-1));if(p){ans+=p;change(1,1,n,a[i].x,a[i].y-1,p);}}printf("%d\n",ans);return 0; } AC

?

解謎游戲(puzzle)

Time Limit:1000ms?? Memory Limit:128MB

?

題目描述

LYK進了一家古董店,它很想買其中的一幅畫。但它帶的錢不夠買這幅畫。

幸運的是,老板正在研究一個問題,他表示如果LYK能幫他解出這個問題的話,就把這幅畫送給它。

老板有一個n*m的矩陣,他想找一個和最大的子矩陣,這個子矩陣可以由四個參數x,y,x2,y2(1<=x<=x2<=n,1<=y<=y2<=m)來表示,表示一個左上角為(x,y),右下角為(x2,y2)的矩陣。

為了讓游戲更加有趣,老板給了一個常數P,他想將原來這個矩陣中恰好一個數變為P,使得這個矩陣的最大的子矩陣盡可能大。

老板想知道這個最大值是多少。

你能幫幫LYK嗎?

?

輸入格式(puzzle.in)

??? 第一行三個數n,m,P。

??? 接下來n行,每行m個數ai,j描述整個矩陣。

?

輸出格式(puzzle.out)

??? 輸出一個數表示答案。

?

輸入樣例

3 3 3

-100 3 3

3 -4 3

3 3 3

?

輸出樣例

20

?

樣例解釋

改變左上角那個數。

?

數據范圍

對于20%的數據n,m<=10。

對于40%的數據n,m<=25。

對于60%的數據n,m<=50。

對于80%的數據n,m<=100。

對于100%的數據1<=n,m<=300,|P|,|ai,j|<=1000。

?

題解:

#include<iostream> #include<cstdio> #include<cstring> using namespace std;int n,m,p,ans; int sum[320][320],a[320][320];bool init(int x,int y,int zx,int zy,int yx,int yy){if(x>=zx&&x<=yx&&y>=zy&&y<=yy)return true;return false; }int main(){freopen("puzzle.in","r",stdin);freopen("puzzle.out","w",stdout);scanf("%d%d%d",&n,&m,&p);//n行m列改成pfor(int i=1;i<=n;i++){for(int j=1;j<=m;j++){scanf("%d",&a[i][j]);sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+a[i][j];} } ans=-0x7ffffff;for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){for(int h=1;h<=m;h++){for(int l=1;l<=n;l++){for(int u=1;u+l-1<=n;u++){for(int v=1;v+h-1<=m;v++){int hang=u+l-1,lie=v+h-1;int all=sum[hang][lie]-sum[hang][v-1]-sum[u-1][lie]+sum[u-1][v-1];if(init(i,j,u,v,hang,lie))ans=max(ans,all-a[i][j]+p);else ans=max(ans,all);}}}}}}printf("%d\n",ans); fclose(stdin);fclose(stdout);return 0; } 前綴和優化暴力40

?正解:dp

先看一個經典問題,求一個序列的最大子段和。我們是可以O(n)求的。

dp轉移方程:f[i]=max(f[i-1]+a[i],a[i]) 對于每個數字,它可以加入前一段也可以單獨一塊。

那么對于要求修改一次的序列呢?假如要求把a[i]->p

f[i][0]=max(f[i-1][0]+a[i],a[i])和f[i][1]=max{f[i-1][0]+p,p,f[i-1][1]+a[i]}

我們可以求出矩陣每一列的前綴和,枚舉子矩陣的上下邊界,a[i]=矩陣這

一列上下界之前的和,那么這個問題就和我們開始的經典問題沒有差別了。

代碼:

#include<iostream> #include<cstdio> #include<cstring> #define inf 1000000000 using namespace std;int n,m,p,ans,map[310][310],sum[310][310],mn[310],a[310],dp[310][3];int main(){scanf("%d%d%d",&n,&m,&p);for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){scanf("%d",&map[i][j]);sum[i][j]=map[i][j];sum[i][j]+=sum[i-1][j];}}for(int tu=1;tu<=n;tu++){for(int i=1;i<=m;i++)mn[i]=map[tu][i];for(int td=tu;td<=n;td++){for(int i=1;i<=m;i++)mn[i]=min(mn[i],map[td][i]);for(int i=1;i<=m;i++)a[i]=sum[td][i]-sum[tu-1][i];dp[0][1]=-inf;for(int i=1;i<=m;i++){dp[i][0]=max(dp[i-1][0]+a[i],a[i]);dp[i][1]=max(max(dp[i-1][1]+a[i],a[i]-mn[i]+p),dp[i-1][0]-mn[i]+p+a[i]);}if(tu==1&&td==n)ans=max(ans,dp[m][1]);else for(int i=1;i<=m;i++)ans=max(ans,max(dp[i][0],dp[i][1]));}}printf("%d\n",ans);return 0; } AC

?

轉載于:https://www.cnblogs.com/zzyh/p/7624443.html

總結

以上是生活随笔為你收集整理的2017.10.3北京清北综合强化班DAY3的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。