链接:http://codeforces.com/contest/731
感觉自己好菜啊,这么简单的题都没AK。。。还有它为什么不按套路出牌啊,F题比E题简单。。。
A题:大水题,模拟,不说了。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 int n,ans; 8 char s[105]; 9 int read(){ 10 int x=0,f=1;char ch; 11 for(ch=getchar();ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1; 12 for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0'; 13 return x*f; 14 } 15 int main(){ 16 scanf("%s",s+1);n=strlen(s+1); 17 char p='a'; 18 for(int i=1;i<=n;i++){ 19 int xx=abs(s[i]-p); 20 ans+=min(xx,26-xx); 21 p=s[i]; 22 } 23 printf("%d ",ans); 24 return 0; 25 }
B题:也是大水题。。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 int n,a[200005]; 8 int read(){ 9 int x=0,f=1;char ch; 10 for(ch=getchar();ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1; 11 for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0'; 12 return x*f; 13 } 14 int main(){ 15 n=read(); 16 for(int i=1;i<=n;i++)a[i]=read(); 17 for(int i=1;i<=n;i++){ 18 if(a[i]<0){puts("NO");return 0;} 19 else{ 20 a[i]%=2;if(a[i])a[i]--,a[i+1]--; 21 } 22 } 23 if(a[n+1]<0)puts("NO"); 24 else puts("YES"); 25 return 0; 26 }
C题:就是找出同一个联通块中出现最多的颜色的出现次数。。。我还傻逼的写了一个线段树。。。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 typedef long long ll; 8 typedef double ld; 9 typedef unsigned long long ull; 10 int n,m,k,tot,num,cnt,fa[200005],a[200005],h[200005],way[200005*2],fuck[200005*2],sum[200005],t[200005*4],v[200005]; 11 int ans; 12 int read(){ 13 int x=0,f=1;char ch; 14 for(ch=getchar();ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1; 15 for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0'; 16 return x*f; 17 } 18 void insert(int x,int y){way[++tot]=y;fuck[tot]=h[x];h[x]=tot;} 19 void change(int z,int l,int r,int x,int y){ 20 if(l>x||r<x)return; 21 if(l==r){t[z]+=y;return;} 22 int mid=(l+r)>>1; 23 change(z<<1,l,mid,x,y);change(z<<1|1,mid+1,r,x,y); 24 t[z]=max(t[z<<1],t[z<<1|1]); 25 } 26 void dfs(int x,int y,int fa){ 27 v[x]=cnt;change(1,1,k,a[x],y);num++; 28 for(int j=h[x];j;j=fuck[j])if(way[j]!=fa&&v[way[j]]!=cnt){ 29 dfs(way[j],y,x); 30 } 31 } 32 int main(){ 33 n=read();m=read();k=read(); 34 for(int i=1;i<=n;i++)a[i]=read(); 35 for(int i=1,x,y;i<=m;i++){ 36 x=read();y=read(); 37 insert(x,y);insert(y,x); 38 } 39 for(int i=1;i<=n;i++)if(h[i]&&!v[i]){ 40 num=0;cnt++;dfs(i,1,0);ans+=num-t[1];cnt++;dfs(i,-1,0); 41 } 42 printf("%d ",ans); 43 return 0; 44 }
D题:考虑找出使相邻两个词按字典序排列的答案范围,求一下交集就好了。。。然而我还是傻逼的写了个线段树。。。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<cmath> 5 #include<algorithm> 6 #define maxn 500005 7 #define maxc 1000005 8 using namespace std; 9 int n,c,a[maxn],b[maxn],t[maxc*4],bj[maxc*4]; 10 int read(){ 11 int x=0,f=1;char ch; 12 for(ch=getchar();ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1; 13 for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0'; 14 return x*f; 15 } 16 void down(int z,int l,int r){ 17 if(bj[z]!=-1&&l!=r){ 18 t[z<<1]=bj[z];t[z<<1|1]=bj[z]; 19 bj[z<<1]=bj[z];bj[z<<1|1]=bj[z]; 20 } 21 bj[z]=-1; 22 } 23 void change(int z,int l,int r,int x,int y,int w){ 24 if(x>y)return; 25 if(l>y||r<x)return; 26 down(z,l,r); 27 if(l>=x&&r<=y){t[z]=w;bj[z]=w;return;} 28 int mid=(l+r)>>1; 29 change(z<<1,l,mid,x,y,w);change(z<<1|1,mid+1,r,x,y,w); 30 t[z]=t[z<<1]|t[z<<1|1]; 31 } 32 int query(int z,int l,int r){ 33 down(z,l,r); 34 if(t[z]==0)return -1; 35 if(l==r)return l; 36 int mid=(l+r)>>1; 37 if(t[z<<1])return query(z<<1,l,mid); 38 else query(z<<1|1,mid+1,r); 39 } 40 int main(){ 41 n=read();c=read(); 42 memset(bj,-1,sizeof(bj)); 43 for(int i=1;i<=4*c;i++)t[i]=1; 44 a[0]=read();for(int i=1;i<=a[0];i++)a[i]=read(); 45 for(int i=2;i<=n;i++){ 46 b[0]=read();for(int j=1;j<=b[0];j++)b[j]=read(); 47 for(int j=1;j<=a[0];j++){ 48 if(j>b[0]){change(1,0,c-1,0,c-1,0);break;} 49 if(a[j]!=b[j]){ 50 int x=a[j],y=b[j]; 51 if(x<y)change(1,0,c-1,c-y+1,c-x,0); 52 else change(1,0,c-1,0,c-x,0),change(1,0,c-1,c-y+1,c-1,0); 53 break; 54 } 55 } 56 for(int j=0;j<=b[0];j++)a[j]=b[j]; 57 } 58 printf("%d ",query(1,0,c-1)); 59 return 0; 60 }
E题:设dp[i]代表1~i-1都被取完时,先手与后手的最大得分差,dp[i]=max(sum[j]-dp[j])(j>i),答案即为dp[1]。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<cmath> 5 #include<algorithm> 6 #define maxn 200005 7 using namespace std; 8 typedef long long ll; 9 typedef double ld; 10 typedef unsigned long long ull; 11 const ll inf=1e18; 12 int n,m; 13 ll a[maxn],ans; 14 int read(){ 15 int x=0,f=1;char ch; 16 for(ch=getchar();ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1; 17 for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0'; 18 return x*f; 19 } 20 int main(){ 21 n=read(); 22 for(int i=1;i<=n;i++)a[i]=read(); 23 for(int i=1;i<=n;i++)a[i]+=a[i-1]; 24 ans=a[n]; 25 for(int i=n-1;i>1;i--)ans=max(ans,a[i]-ans); 26 printf("%I64d ",ans); 27 return 0; 28 }
F题:枚举选择的数i,再枚举j表示减完后是什么数,统计答案即可。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<cmath> 5 #include<algorithm> 6 #define maxn 1000005 7 using namespace std; 8 typedef long long ll; 9 typedef double ld; 10 typedef unsigned long long ull; 11 int n,m,a[maxn],f[maxn]; 12 ll ans,sum; 13 int read(){ 14 int x=0,f=1;char ch; 15 for(ch=getchar();ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1; 16 for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0'; 17 return x*f; 18 } 19 int main(){ 20 n=read(); 21 for(int i=1,x;i<=n;i++){ 22 x=read();a[x]++; 23 } 24 for(int i=200000;i;i--)f[i]=f[i+1]+a[i]; 25 for(int i=1;i<=200000;i++)if(a[i]){ 26 sum=0; 27 for(int j=i;j<=200000;j+=i)sum+=(ll)(f[j]-f[j+i])*j; 28 ans=max(ans,sum); 29 } 30 printf("%I64d ",ans); 31 return 0; 32 }