Codeforces Round #171 (Div. 2)
a. 最近做过的最痛苦的a题。 平时a题最多也就5分钟,可是这题我却卡了近一个小时。
题意很简单,以一种规则画圈, 然后求给出点需要转多少次方向.
找规律方法
1 #include <stdio.h> 2 #include <string.h> 3 #include <math.h> 4 #include <algorithm> 5 #include <iostream> 6 using namespace std; 7 8 9 int main() 10 { 11 int x,y; 12 scanf("%d%d",&x,&y); 13 int sum; 14 if(x>0&&x*-1==y) 15 { 16 sum=4+4*(x-1); 17 printf("%d",sum); 18 return 0; 19 } 20 if(abs(x)>=abs(y)) 21 { 22 if(x>=0) 23 { 24 if(x==0) 25 { 26 sum=0; 27 } 28 else 29 { 30 sum=4*(x-1)+1; 31 if(-1*y==x-1) sum--; 32 } 33 } 34 else 35 { 36 sum=3+4*(-1*x-1); 37 if(-1*x==y) sum--; 38 } 39 } 40 else 41 { 42 if(y>=0) 43 { 44 sum=2+4*(y-1); 45 if(x==y) sum--; 46 } 47 else 48 { 49 sum=4+4*(-1*y-1); 50 if(x==y) sum--; 51 } 52 } 53 printf("%d",sum); 54 return 0; 55 }
模拟
b. 队列简单题
#include <stdio.h> #include <string.h> #define N 100100 int g[N],k[N]; int main() { int n,t; scanf("%d%d",&n,&t); int qf=0,qd=0; int sum=0; int mx=0; int cnt=0; for(int i=0;i<n;i++) { int tmp; scanf("%d",&tmp); g[i]=tmp; if(tmp>t) { cnt=0; qd=i+1; sum=0; continue; } if(sum+tmp<=t) { sum+=tmp; cnt++; if(cnt>mx) mx=cnt; } else { while(sum+tmp>t) { sum-=g[qd++]; cnt--; } sum+=tmp; cnt++; if(cnt>mx) mx=cnt; } } printf("%d",mx); return 0; }
c. 判断给定区域内的线段是否成梯形(单调递增 或单调递减或 先整后减), 可以用用两个数组记录整个线段的变换情况。 然后在判断就行了。
#include <stdio.h> #include <string.h> #include <iostream> using namespace std; #define N 100100 #define INF 0x3fffffff int g[N]; int mi[N],mx[N]; int main() { int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&g[i]); int qd=1; int tmp=-1; for(int i=1;i<=n;i++) { if(g[i]>=tmp) { tmp=g[i]; } else { tmp=g[i]; for(int j=qd;j<=i-1;j++) { mx[j]=i-1; } qd=i; } if(i==n) { for(int j=qd;j<=i;j++) mx[j]=i; } } qd=1; tmp = INF; for(int i=1;i<=n;i++) { if(g[i]<=tmp) { tmp=g[i]; } else { tmp=g[i]; for(int j=qd;j<=i-1;j++) { mi[j]=i-1; } qd=i; } if(i==n) { for(int j=qd;j<=i;j++) { mi[j]=i; } } } for(int i=0;i<m;i++) { int x,y; scanf("%d%d",&x,&y); if(mx[x]>=y||mi[x]>=y) printf("Yes\n"); else { if(mi[mx[x]]>=y) printf("Yes\n"); else printf("No\n"); } } return 0; }
e. 用dp或者贪心都可以做, 关键是要将问题模型转换, 题中所说的可以增加2^k 或 -2^k . 实际上的意思是用一次操作改变一位,或用两次操作改变一段. 这样就可以想到贪心规则,和状态转移方程了...
DP 解法
1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 #include <iostream> 5 using namespace std; 6 #define N 1000100 7 8 char g[N]; 9 int save[N]; 10 int dp[N]; 11 int dp1[N]; 12 13 int min1(int x,int y) 14 { 15 if(x>y) return y; 16 else return x; 17 } 18 int main() 19 { 20 scanf("%s",g); 21 int i=0; 22 int cnt=0; 23 while(g[i]=='0') 24 { 25 i++; 26 } 27 int len = strlen(g); 28 if(i==len) 29 { 30 printf("0"); 31 return 0; 32 } 33 char tmp='1'; 34 int tcnt=0; 35 for(;i<=len;i++) 36 { 37 if(tmp==g[i]&&i!=len) 38 { 39 tcnt++; 40 } 41 else 42 { 43 tmp=g[i]; 44 save[cnt++]=tcnt; 45 tcnt=1; 46 } 47 } 48 if(cnt%2==0) cnt--; // 当最后一位0的时候,省略 49 50 dp[0]=save[0]; 51 dp1[0]=2; 52 53 for(int j=2;j<cnt;j++) 54 { 55 dp[j]=min1(dp[j-2],dp1[j-2])+save[j]; 56 dp1[j]=min1(min1(dp[j-2]+2,dp1[j-2]+save[j-1]),dp1[j-2]+2); 57 j++; 58 } 59 printf("%d",min1(dp[cnt-1],dp1[cnt-1])); 60 return 0; 61 }