2017-10-03
T1 括號序列(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|是偶數。
1 /* 2 從左往右掃過來,遇到一個),觀察之前有沒有(, 3 如果有的話就抵消掉。 4 如果沒有的話 -> 把這個字符變成( 操作數記為X 5 6 一直這麽做,掃完整個字符串之後, 7 最終一定匹配完後剩下一堆左括號。 個數記為 Y 8 則ans=x+y/2 9 */ 10 #include <cstring> 11AC#include <cstdio> 12 13 const int N(100005); 14 int n,top,ans; 15 char s[N]; 16 17 int Presist() 18 { 19 // freopen("bracket.in","r",stdin); 20 // freopen("bracket.out","w",stdout); 21 scanf("%s",s); n=strlen(s); 22 for(int i=0; i<n; ++i) 23 { 24 if(s[i]==‘(‘) top++; //記錄左括號個數(y值) 25 else 26 { 27 if(top<1) top++,ans++; 28 //沒有左括號可與右括號匹配,將右括號變為左括號,累加x值 29 else top--; //抵消左括號和右括號 30 } 31 } 32 printf("%d\n",ans+top/2); 33 return 0; 34 } 35 36 int Aptal=Presist(); 37 int main(int argc,char*argv[]){;}
T2 公交車(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。
1 #include <cstdio> 2 #include <vector> 3 #include <queue> 4 5 inline void read(int &x) 6 { 7 x=0; register char ch=getchar(); 8 for(; ch>‘9‘||ch<‘0‘; ) ch=getchar(); 9 for(; ch>=‘0‘&&ch<=‘9‘; ch=getchar()) x=x*10+ch-‘0‘; 10 } 11 const int N=20010; 12 int n,m,k,ans,sum[N]; 13 14 struct node 15 { 16 int to,val; 17 node() {} 18 node(int to,int val):to(to),val(val) {} 19 }; 20 std::vector<node> G[N]; 21 22 void DFS(int num,int s,int people) 23 { 24 if(num==n+1) 25 { 26 ans=s>ans?s:ans; 27 return; 28 } 29 people+=sum[num]; 30 sum[num]=0; 31 for(int i=0; i<G[num].size(); ++i) 32 { 33 int v=G[num][i].to; 34 int ps=G[num][i].val; 35 if(ps<=k-people) 36 { 37 sum[v]+=-ps; 38 DFS(num+1,s+ps,people+ps); 39 } 40 else if((people<k)&&(ps+people>k)) 41 { 42 sum[v]+=people-k; 43 DFS(num+1,s+k-people,k); 44 } 45 } 46 DFS(num+1,s,people); 47 return; 48 } 49 50 int Presist() 51 { 52 freopen("bus.in","r",stdin); 53 freopen("bus.out","w",stdout); 54 read(m); read(n); read(k); 55 for(int x,y,v,i=1; i<=m; ++i) 56 { 57 read(x); read(y); read(v); 58 G[x].push_back(node(y,v)); 59 } 60 DFS(1,0,0); 61 printf("%d\n",ans); 62 return 0; 63 } 64 65 int Aptal=Presist(); 66 int main(int argc,char*argv){;}爆搜30分
1 /* 2 貪心做法 3 給怪獸以下車點為第一關鍵字排序、 4 每次讓盡量多的怪獸上車 5 每一只怪獸上車時讓上車時間盡量靠近前一個怪獸 6 f[]記錄每個車上空間空出的時間 7 */ 8 #include <algorithm> 9 #include <cstdio> 10 11 inline void read(int &x) 12 { 13 x=0; register char ch=getchar(); 14 for(; ch>‘9‘||ch<‘0‘; ) ch=getchar(); 15 for(; ch>=‘0‘&&ch<=‘9‘; ch=getchar()) x=x*10+ch-‘0‘; 16 } 17 const int N(50005); 18 int k,n,c,ans,f[N]; 19 struct Cow { 20 int l,r,val; 21 bool operator < (const Cow &x)const 22 { 23 if(r==x.r) return l>x.l; 24 return r<x.r; 25 } 26 }node[N]; 27 28 int Presist() 29 { 30 read(k),read(n),read(c); 31 for(int i=1; i<=k; ++i) 32 read(node[i].l),read(node[i].r),read(node[i].val); 33 std:: sort(node+1,node+k+1); 34 for(int i=1,x,t; i<=k; ++i) 35 { 36 if(node[i].l<f[1]) continue; 37 for(x=1; x<=node[i].val&&x<=c&&node[i].l>=f[x]; ) 38 x++; x--; //減去多出node[i].val的哪一個怪獸 39 for(t=1; t<=c; ++t) 40 if(node[i].l<f[t]) break; 41 //t是第一個空出時間晚於當前怪獸上車時間的車位 42 t-=x; 43 for(; f[t+x]<=node[i].r&&t+x<=c; ) 44 f[t]=f[t+x],t++; //車位號向前更新 45 for(int j=1; j<=x; ++j) f[t++]=node[i].r; 46 ans+=x; 47 } 48 printf("%d\n",ans); 49 return 0; 50 } 51 52 int Aptal=Presist(); 53 int main(int argc,char**argv){;}貪心 AC
1 /* 2 求這一群怪獸能過幾只 3 維護一個f數組 f[i]表示i這個時刻 4 車上已經坐了幾只怪獸了 5 [X,Y] Z 6 for (int i=X; i<Y; i++) 7 MAX=max(MAX,f[i]); 8 t=min(Z,M-MAX); 9 for (int i=X; i<Y; i++) f[i]+=t; 10 ans+=t 11 1.區間+ 2.區間查詢最大值 12 線段樹維護 klgn 13 */ 14 #include <cmath> 15 #include <cstdio> 16 #include <cstdlib> 17 #include <iostream> 18 #include <algorithm> 19 using namespace std; 20 int tree[65536][4],n,m,c,i,MIN,ans; 21 struct node 22 { 23 int x; 24 int y; 25 int z; 26 }; 27 node A[100005]; 28 int cmp(node i,node j) 29 { 30 return i.y<j.y; 31 } 32 void Update(int k) 33 { 34 tree[k*2][2]+=tree[k][3]; 35 tree[k*2+1][2]+=tree[k][3]; 36 tree[k*2][3]+=tree[k][3]; 37 tree[k*2+1][3]+=tree[k][3]; 38 tree[k][3]=0; 39 } 40 void work(int root,int l,int r,int k) 41 { 42 if (l==tree[root][0] && r==tree[root][1]) 43 { 44 tree[root][2]+=k; 45 tree[root][3]+=k; 46 return; 47 } 48 Update(root); 49 int mid=(tree[root][0]+tree[root][1])/2; 50 if (l<=mid) work(root*2,l,min(mid,r),k); 51 if (r>mid) work(root*2+1,max(mid+1,l),r,k); 52 tree[root][2]=min(tree[root*2][2],tree[root*2+1][2]); 53 } 54 int find(int root,int l,int r) 55 { 56 if (l==tree[root][0] && r==tree[root][1]) return tree[root][2]; 57 Update(root); 58 int mid=(tree[root][0]+tree[root][1])/2,p=453266144,q=453266144; 59 if (l<=mid) p=find(root*2,l,min(mid,r)); 60 if (r>mid) q=find(root*2+1,max(mid+1,l),r); 61 return min(p,q); 62 } 63 int main() 64 { 65 freopen("bus.in","r",stdin); 66 freopen("bus.out","w",stdout); 67 scanf("%d%d%d",&n,&m,&c); 68 for (i=32768; i<=65535; i++) tree[i][0]=tree[i][1]=i; 69 for (i=32767; i>=1; i--) 70 { 71 tree[i][0]=tree[i*2][0]; 72 tree[i][1]=tree[i*2+1][1]; 73 } 74 work(1,1+32767,m+32767,c); 75 for (i=1; i<=n; i++) 76 { 77 scanf("%d%d%d",&A[i].x,&A[i].y,&A[i].z); 78 A[i].y--; 79 } 80 sort(A+1,A+n+1,cmp); 81 for (i=1; i<=n; i++) 82 { 83 MIN=find(1,A[i].x+32767,A[i].y+32767); 84 if (MIN>A[i].z) 85 { 86 work(1,A[i].x+32767,A[i].y+32767,-A[i].z); 87 ans+=A[i].z; 88 } 89 else 90 { 91 work(1,A[i].x+32767,A[i].y+32767,-MIN); 92 ans+=MIN; 93 } 94 } 95 cout<<ans; 96 return 0; 97 }std 線段樹維護
解謎遊戲(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。
1 #include <cstring> 2 #include <cstdio> 3 4 #define min(a,b) (a<b?a:b) 5 #define max(a,b) (a>b?a:b) 6 #define LL long long 7 const int N(305); 8 int n,m,p,a[N][N]; 9 long long ans,tmp,sum[N][N]; 10 int change,min_[N][N][N]; 11 12 inline void violence() 13 { 14 /*40分做法 15 暴力枚舉更改的點n^ 2 16 樸素的最大子矩陣n^2*m。 17 */ 18 for(int q=1; q<=n; ++q) 19 for(int h=1; h<=m; ++h) 20 { 21 for(int i=1; i<=n; ++i) 22 for(int j=1; j<=m; ++j) 23 sum[i][j]=a[i][j]; 24 sum[q][h]=max(sum[q][h],p); 25 for(int i=1; i<=n; ++i) 26 for(int j=1; j<=m; ++j) 27 sum[i][j]+=sum[i-1][j]; 28 for(int top=0; top<n; ++top) 29 for(int i=top+1; i<=n; ++i) 30 { 31 for(int j=1; j<=m; ++j) 32 { 33 if(tmp<0) tmp=(LL)sum[i][j]-sum[top][j]; 34 else tmp+=(LL)sum[i][j]-sum[top][j]; 35 ans=max(ans,tmp); 36 } tmp=0; 37 } 38 } 39 printf("%I64d\n",ans); 40 } 41 inline void WA() 42 { 43 /* 44 處理出每行的每段中的最小值、判斷是否作為p被替換掉 45 但是WA掉了。。。 46 */ 47 for(int i=0; i<=n; ++i) 48 for(int j=0; j<=n; ++j) 49 for(int k=0; k<=m; ++k) 50 min_[i][j][k]=0x7fffffff; 51 for(int i=1; i<=n; ++i) 52 for(int j=1; j<=m; ++j) 53 { 54 min_[i-1][i][j]=a[i][j]; 55 sum[i][j]=sum[i-1][j]+a[i][j]; 56 } 57 for(int top=0; top<n; ++top) 58 for(int i=top+1; i<=n; ++i) 59 for(int j=1;j<=m; ++j) 60 min_[top][i][j]=min(min_[top][i][j],min_[top][i-1][j]); 61 for(int top=0; top<n; ++top) 62 for(int i=top+1; i<=n; ++i) 63 { 64 for(int j=1; j<=m; ++j) 65 { 66 change=min(change,min_[top][i][j]); 67 if(tmp-change+p<0) 68 change=0x7fffffff,tmp=(LL)sum[i][j]-sum[top][j]; 69 else tmp+=(LL)sum[i][j]-sum[top][j]; 70 ans=max(ans,tmp-change+p); 71 } tmp=0; change=0x7fffffff; 72 } 73 printf("%I64d\n",ans); 74 } 75 76 int Presist() 77 { 78 freopen("puzzle.in","r",stdin); 79 freopen("puzzle.out","w",stdout); 80 scanf("%d%d%d",&n,&m,&p); 81 for(int i=1; i<=n; ++i) 82 for(int j=1; j<=m; ++j) 83 scanf("%d",&a[i][j]); 84 if(n<=25&&m<=25) violence(); 85 else WA(); 86 return 0; 87 } 88 89 int Aptal=Presist(); 90 int main(int argc,char*argv[]){;}40分
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define N 305 using namespace std; int n,m,p,ans,d[N],s[N][N],minn[N],a[N][N],dp[N][N]; int read() { int x=0,f=1; char ch=getchar(); while(ch<‘0‘||ch>‘9‘) {if(ch==‘-‘)f=-1; ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar(); return x*f; } int main() { n=read(),m=read(),p=read(); ans=-1000000000; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) a[i][j]=read(),s[i][j]=s[i-1][j]+a[i][j];//預處理前綴和 for(int i=1;i<=n;i++)//枚舉上邊界 { for(int j=1;j<=m;j++) minn[j]=a[i][j];//預處理每一列裏的最小值 for(int j=i;j<=n;j++)//枚舉下邊界 { for(int k=1;k<=m;k++) minn[k]=min(minn[k],a[j][k]);// for(int k=1;k<=m;k++) d[k]=s[j][k]-s[i-1][k];//處理出在上邊界與下邊界圍成的這個地方每一列的和 dp[0][1]=-1000000000; for(int k=1;k<=m;k++) { dp[k][0]=max(dp[k-1][0]+d[k],d[k]); dp[k][1]=max(max(dp[k-1][1]+d[k],d[k]-minn[k]+p),dp[k-1][0]+d[k]-minn[k]+p); } if(i==1&&j==n) ans=max(ans,dp[m][1]); else ans=max(ans,max(dp[m][1],dp[m][0])); for(int k=1;k<=m;k++) ans=max(ans,max(dp[k][1],dp[k][0])); } } printf("%d",ans); return 0; }
2017-10-03