Codeforces Round #171 (Div. 2)
A.yy题,分情况讨论比较方便,详见代码。
View Code
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 #include<math.h> 5 #include<iostream> 6 #include<string> 7 #include<algorithm> 8 #include<vector> 9 #include<queue> 10 #include<stack> 11 using namespace std; 12 #define LL __int64 13 #define pdi pair<int,int> 14 #define Max(a,b) ((a)>(b)?(a):(b)) 15 #define Min(a,b) ((a)<(b)?(a):(b)) 16 #define mem(a,b) memset(a,b,sizeof(a)) 17 #define lson l,mid,rt<<1 18 #define rson mid+1,r,rt<<1|1 19 const int N=110,INF=0x3f3f3f3f,MOD=100000000; 20 const double DNF=100000000000; 21 22 int main() 23 { 24 // freopen("in.txt","r",stdin); 25 int x,y,ans; 26 while(~scanf("%d%d",&x,&y)) 27 { 28 if(x==0 && y==0)ans=0; 29 else if(y<=0 && x>y && x<=-y+1)ans=-4*y; 30 else if(x>0 && y>-x+1 && y<=x)ans=4*(x-1)+1; 31 else if(y>0 && x<y && x>=-y)ans=4*(y-1)+2; 32 else ans=4*(-x-1)+3; 33 printf("%d\n",ans); 34 } 35 return 0; 36 }
B.从第一个数开始,维护一个最长的区间即可。
View Code
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 #include<math.h> 5 #include<iostream> 6 #include<string> 7 #include<algorithm> 8 #include<vector> 9 #include<queue> 10 #include<stack> 11 using namespace std; 12 #define LL __int64 13 #define pdi pair<int,int> 14 #define Max(a,b) ((a)>(b)?(a):(b)) 15 #define Min(a,b) ((a)<(b)?(a):(b)) 16 #define mem(a,b) memset(a,b,sizeof(a)) 17 #define lson l,mid,rt<<1 18 #define rson mid+1,r,rt<<1|1 19 const int N=100010,INF=0x3f3f3f3f,MOD=100000000; 20 const double DNF=100000000000; 21 22 int t[N]; 23 int n,m; 24 25 int main() 26 { 27 // freopen("in.txt","r",stdin); 28 int i,j,ans,sum,w; 29 while(~scanf("%d%d",&n,&m)) 30 { 31 ans=0; 32 for(i=1;i<=n;i++) 33 scanf("%d",&t[i]); 34 sum=m; 35 for(i=1,w=0;i<=n;i++){ 36 sum-=t[i]; 37 while(sum<0)sum+=t[++w]; 38 ans=Max(ans,i-w); 39 } 40 41 printf("%d\n",ans); 42 } 43 return 0; 44 }
C.DP,用两个数组分别记录每个数的左边最多连续降序的数个数和右边最多连续降序的数个数。还可以用线段树来做。
View Code
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 #include<vector> 5 #include<queue> 6 #include<math.h> 7 #include<map> 8 #include<set> 9 using namespace std; 10 #define LL __int64 11 #define pii pair<int,int> 12 #define lson l,mid,rt<<1 13 #define rson mid+1,r,rt<<1|1 14 const int N=100010,INF=200000000; 15 const double esp=1e-6; 16 17 int num[N],lonl[N<<2],lonr[N<<2]; 18 int n,m,a,b,ans,maxl,wl,okl,okr,wr,maxr; 19 20 void buildl(int l,int r,int rt) 21 { 22 if(l==r){ 23 lonl[rt]=l; 24 return; 25 } 26 int mid=(l+r)>>1; 27 buildl(lson); 28 buildl(rson); 29 if(lonl[rt<<1]==mid && num[mid]<=num[mid+1]) 30 lonl[rt]=lonl[rt<<1|1]; 31 else lonl[rt]=lonl[rt<<1]; 32 return; 33 } 34 35 void buildr(int l,int r,int rt) 36 { 37 if(l==r){ 38 lonr[rt]=l; 39 return; 40 } 41 int mid=(l+r)>>1; 42 buildr(rson); 43 buildr(lson); 44 if(lonr[rt<<1|1]==mid+1 && num[mid]>=num[mid+1]) 45 lonr[rt]=lonr[rt<<1]; 46 else lonr[rt]=lonr[rt<<1|1]; 47 } 48 49 void queryl(int l,int r,int rt) 50 { 51 if(a<=l && r<=b){ 52 if(num[l]>=maxl && okl){ 53 wl=lonl[rt]; 54 maxl=num[wl]; 55 if(wl!=r)okl=0; 56 } 57 else okl=0; 58 return; 59 } 60 int mid=(l+r)>>1; 61 if(a<=mid)queryl(lson); 62 if(b>mid)queryl(rson); 63 } 64 65 void queryr(int l,int r,int rt) 66 { 67 if(a<=l && r<=b){ 68 if(num[r]>=maxr && okr){ 69 wr=lonr[rt]; 70 maxr=num[wr]; 71 if(wr!=l)okr=0; 72 } 73 else okr=0; 74 return; 75 } 76 int mid=(l+r)>>1; 77 if(b>mid)queryr(rson); 78 if(a<=mid)queryr(lson); 79 } 80 81 int main() 82 { 83 // freopen("in.txt","r",stdin); 84 int i,j; 85 while(~scanf("%d%d",&n,&m)) 86 { 87 for(i=1;i<=n;i++) 88 scanf("%d",&num[i]); 89 buildl(1,n,1); 90 buildr(1,n,1); 91 while(m--){ 92 scanf("%d%d",&a,&b); 93 okl=okr=1; 94 maxl=maxr=0; 95 queryl(1,n,1); 96 queryr(1,n,1); 97 printf("%s\n",wl>=wr?"Yes":"No"); 98 } 99 } 100 return 0; 101 }
D.状态压缩DP,注意到第i个数是由0...i-1个数得到的,而且每次最多会有i个数,因此我们可以用二进制枚举所有情况。
View Code
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 #include<math.h> 5 #include<iostream> 6 #include<string> 7 #include<algorithm> 8 #include<vector> 9 #include<queue> 10 #include<stack> 11 using namespace std; 12 #define LL __int64 13 #define pii pair<int,int> 14 #define Max(a,b) ((a)>(b)?(a):(b)) 15 #define Min(a,b) ((a)<(b)?(a):(b)) 16 #define mem(a,b) memset(a,b,sizeof(a)) 17 #define lson l,mid,rt<<1 18 #define rson mid+1,r,rt<<1|1 19 const int N=23,INF=0x3f3f3f3f,MOD=100000000; 20 const double DNF=100000000000; 21 22 bool f[1<<N]; 23 int num[N]; 24 int n; 25 26 int ok(int stu,int up) 27 { 28 int i,j; 29 for(i=0;i<up;i++) 30 if(stu&(1<<i)) 31 for(j=i;j<up;j++) 32 if(stu&(1<<j) && num[i]+num[j]==num[up]) 33 return 1; 34 return 0; 35 } 36 37 int main() 38 { 39 // freopen("in.txt","r",stdin); 40 int k,i,j,up,down,cnt,ans; 41 scanf("%d",&n); 42 for(i=0;i<n;i++) 43 scanf("%d",&num[i]); 44 f[1]=1; 45 for(i=1;i<n;i++){ 46 up=(1<<(i+1));down=(1<<i); 47 for(j=down+(down>>1);j<up;j++){ 48 if(f[j-down] && ok(j,i)){ 49 f[j]=1; 50 for(k=0;k<i;k++)f[j&~(1<<k)]=1; 51 } 52 } 53 } 54 ans=cnt=INF; 55 up=(1<<n); 56 for(i=(1<<(n-1));i<up;i++){ 57 if(f[i]){ 58 for(j=cnt=0;j<n;j++) 59 cnt+=(i&(1<<j))?1:0; 60 } 61 if(cnt<ans)ans=cnt; 62 } 63 printf("%d\n",ans==INF?-1:ans); 64 return 0; 65 }
E.贪心或者DP.如果 1111 可以只用两个2^k次幂表示,但是如果 10101 的话用 2^4+2^2+2^0 表示比用 2^5-2^3-2^2-2^0表示比较优,因此分这两种特殊考虑,如果有多个0则分子区间考虑。DP:每个数用两种状态,即 2^k 和 2^(k+1)-2^k 因此 f[i][2]用来表示状态,转移方程为:
s[n]=='1':f[p][0]=Min(f[!p][0]+1,f[!p][1]+1);f[p][1]=Min(f[!p][0]+2,f[!p][1]);
s[n]=='0':f[p][0]=Min(f[!p][0],f[!p][1]);f[p][1]=Min(f[!p][0]+2,f[!p][1]+1);
Greedy Method:
View Code
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 #include<math.h> 5 #include<iostream> 6 #include<string> 7 #include<algorithm> 8 #include<vector> 9 #include<queue> 10 #include<stack> 11 using namespace std; 12 #define LL __int64 13 #define pdi pair<int,int> 14 #define Max(a,b) ((a)>(b)?(a):(b)) 15 #define Min(a,b) ((a)<(b)?(a):(b)) 16 #define mem(a,b) memset(a,b,sizeof(a)) 17 #define lson l,mid,rt<<1 18 #define rson mid+1,r,rt<<1|1 19 const int N=1000010,INF=0x3f3f3f3f,MOD=100000000; 20 const double DNF=100000000000; 21 22 char s[N]; 23 24 int main() 25 { 26 // freopen("in.txt","r",stdin); 27 int i,j,la,t,couz,couo,len,ans,ok; 28 scanf("%s",s); 29 len=strlen(s); 30 ans=0; 31 for(i=t=la=0,ok=1;i<len;){ 32 for(couo=0;s[i]=='1' && i<len;i++,couo++); 33 for(couz=0;s[i]=='0' && i<len;i++,couz++); 34 if(i==len)couz=2; 35 if(couz>=2 && ok) 36 ans+=couo>1?2:1; 37 else if(couz==1 || (!ok && couz>=2)){ 38 if(couo>1)la=1; 39 t++; 40 } 41 if(couz>=2 && !ok){ 42 ans+=t+la; 43 t=la=0; 44 } 45 ok=(couz>1); 46 } 47 printf("%d\n",ans); 48 49 return 0; 50 }
DP Method:
View Code
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 #include<math.h> 5 #include<iostream> 6 #include<string> 7 #include<algorithm> 8 #include<vector> 9 #include<queue> 10 #include<stack> 11 using namespace std; 12 #define LL __int64 13 #define pii pair<int,int> 14 #define Max(a,b) ((a)>(b)?(a):(b)) 15 #define Min(a,b) ((a)<(b)?(a):(b)) 16 #define mem(a,b) memset(a,b,sizeof(a)) 17 #define lson l,mid,rt<<1 18 #define rson mid+1,r,rt<<1|1 19 const int N=1000010,INF=0x3f3f3f3f,MOD=100000000; 20 const double DNF=100000000000; 21 22 char s[N]; 23 int f[2][2]; 24 25 int main() 26 { 27 // freopen("in.txt","r",stdin); 28 int n,p; 29 while(~scanf("%s",s)) 30 { 31 n=strlen(s); 32 f[0][0]=0,f[0][1]=INF; 33 for(p=1;n--;p=!p){ 34 if(s[n]=='1'){ 35 f[p][0]=Min(f[!p][0]+1,f[!p][1]+1); 36 f[p][1]=Min(f[!p][0]+2,f[!p][1]); 37 } 38 else { 39 f[p][0]=Min(f[!p][0],f[!p][1]); 40 f[p][1]=Min(f[!p][0]+2,f[!p][1]+1); 41 } 42 // printf("%d %d\n",f[p][0],f[p][1]); 43 } 44 45 printf("%d\n",Min(f[!p][0],f[!p][1])); 46 } 47 return 0; 48 }