Codeforces Round #531 (Div. 3)
Posted lqllulu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #531 (Div. 3)相关的知识,希望对你有一定的参考价值。
A. Integer Sequence Dividing
1 #include <cstdio> 2 3 using namespace std; 4 int n; 5 6 int main(){ 7 scanf("%d",&n); 8 if((n+1)%2==0){ 9 n=(n+1)/2; 10 if(n%2==0){ 11 printf("0 "); 12 }else{ 13 printf("1 "); 14 } 15 }else{ 16 n=n/2; 17 if(n%2==0){ 18 printf("0 "); 19 }else{ 20 printf("1 "); 21 } 22 } 23 24 return 0; 25 }
B. Array K-Coloring
1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 #include <iostream> 5 #include <vector> 6 7 using namespace std; 8 const int maxn=5000+100; 9 int a[maxn],num[maxn]; 10 vector<int>pos[maxn]; 11 int ans[maxn],now[maxn][maxn]; 12 13 int n,k,ty; 14 int main(){ 15 scanf("%d%d",&n,&k); 16 int flag=1; 17 for(int i=1;i<=n;i++){ 18 scanf("%d",&a[i]); 19 if(num[a[i]]==0){ 20 ty++; 21 num[a[i]]=ty; 22 } 23 pos[a[i]].push_back(i); 24 if(pos[a[i]].size()>k){ 25 flag=0; 26 break; 27 } 28 } 29 30 if(n<k){ 31 flag=0; 32 } 33 if(!flag){ 34 printf("NO "); 35 return 0; 36 } 37 for(int i=1;i<=k;i++){ 38 ans[i]=i; 39 now[num[a[i]]][i]=1; 40 } 41 for(int i=k+1;i<=n;i++){ 42 for(int j=1;j<=k;j++){ 43 if(!now[num[a[i]]][j]){ 44 now[num[a[i]]][j]=1; 45 ans[i]=j; 46 break; 47 } 48 } 49 } 50 printf("YES "); 51 for(int i=1;i<=n;i++){ 52 printf("%d ",ans[i]); 53 } 54 55 return 0; 56 }
C. Doors Breaking and Repairing
1 #include <cstdio> 2 #include <algorithm> 3 #include <iostream> 4 #include <cstring> 5 6 using namespace std; 7 const int maxn=100+10; 8 int n,x,y; 9 int a[maxn]; 10 int main(){ 11 scanf("%d%d%d",&n,&x,&y); 12 if(x>y){ 13 printf("%d ",n); 14 return 0; 15 } 16 int num=0; 17 for(int i=1;i<=n;i++){ 18 scanf("%d",&a[i]); 19 if(a[i]<=x) 20 num++; 21 } 22 int ans=num/2; 23 if(num%2)ans++; 24 printf("%d ",ans); 25 return 0; 26 }
D. Balanced Ternary String
1 #include <cstdio> 2 #include <algorithm> 3 #include <iostream> 4 #include <cstring> 5 6 using namespace std; 7 const int maxn=3e5+100; 8 char s[maxn]; 9 int n; 10 int num[3]; 11 int main(){ 12 scanf("%d",&n); 13 scanf("%s",s); 14 for(int i=0;i<n;i++){ 15 int a=s[i]-‘0‘; 16 num[a]++; 17 } 18 int res=n/3; 19 for(int i=0;i<n;i++){ 20 int a=s[i]-‘0‘; 21 if(num[a]>res){ 22 for(int j=0;j<a;j++){ 23 if(num[j]<res){ 24 s[i]=j+‘0‘; 25 num[j]++; 26 num[a]--; 27 break; 28 } 29 } 30 } 31 } 32 for(int i=n-1;i>=0;i--){ 33 int a=s[i]-‘0‘; 34 if(num[a]>res){ 35 for(int j=2;j>a;j--){ 36 if(num[j]<res){ 37 s[i]=j+‘0‘; 38 num[j]++; 39 num[a]--; 40 break; 41 } 42 } 43 } 44 } 45 printf("%s ",s); 46 return 0; 47 }
E. Monotonic Renumeration
显然相同的数字一段必须一样。
1 #include <cstdio> 2 #include <algorithm> 3 #include <iostream> 4 #include <cstring> 5 #include <vector> 6 #include <map> 7 8 using namespace std; 9 typedef long long LL; 10 const int mod=998244353; 11 const int maxn=2e5+10; 12 map<int,int>mp; 13 int a[maxn]; 14 int n; 15 int main(){ 16 scanf("%d",&n); 17 18 for(int i=1;i<=n;i++){ 19 scanf("%d",&a[i]); 20 mp[a[i]]=i; 21 } 22 int right=1; 23 LL ans=1; 24 for(int i=1;i<=n;i++){ 25 if(right>=i) 26 right=max(right,mp[a[i]]); 27 else{ 28 ans=ans*2%mod; 29 right=max(right,mp[a[i]]); 30 } 31 } 32 printf("%I64d ",ans); 33 return 0; 34 }
F. Elongated Matrix
题意
给出一个n*m的矩阵a,每个格子都有一个整数。你可以任意的改变行的顺序,当你确定了一种行的顺序以后,你需要通过下面的方式遍历整个矩阵:首先访问第一列从上到下每个格子,然后第二列。。在遍历的过程中,你要把遍历走过的数字写下了形成一个序列,这个序列为s1,s2,...,snm.
当对于每个i都满足|si-si+1|>=k的时候合法。请找出存在合法序列的最大的整数k。
其中n<=16,m<=10^4.
题解:
个人感觉这是一个好题。
因为行的顺序可以随便换,所以从 第i行可以走到除了i以外的任意行。那么以行为结点,枚举第一行和最后一行,然后在中间的点之间连边,那么就是求从第一行到最后一行,每一行恰好经过一次,路径上最小权值最大。现在就变成了一个哈密顿路径问题。可以通过状态压缩解决。
1 #include <cstdio> 2 #include <algorithm> 3 #include <iostream> 4 #include <cstring> 5 #include <cmath> 6 7 using namespace std; 8 const int INF=2147000000; 9 const int maxn=17; 10 const int maxm=1e4+10; 11 int a[maxn][maxm],Min[maxn][maxn]; 12 int n,m; 13 int dp[1<<maxn][maxn]; 14 15 int solve(int h,int d,int S,int u){ 16 int SS=(1<<n)-1; 17 SS^=(1<<(h-1)); 18 SS^=(1<<(d-1)); 19 if(SS==S)return Min[u][d]; 20 21 if(dp[S][u]!=-1){ 22 return dp[S][u]; 23 } 24 dp[S][u]=0; 25 for(int i=1;i<=n;i++){ 26 if(i!=h&&i!=d&&i!=u){ 27 if(S&(1<<(i-1)))continue; 28 dp[S][u]=max(dp[S][u],min(solve(h,d,S|(1<<(i-1)),i),Min[u][i])); 29 } 30 } 31 // printf("%d %d %d ",S,u,dp[S][u]); 32 return dp[S][u]; 33 } 34 35 int main(){ 36 scanf("%d%d",&n,&m); 37 for(int i=1;i<=n;i++){ 38 for(int j=1;j<=m;j++){ 39 scanf("%d",&a[i][j]); 40 } 41 } 42 if(n==1){ 43 int res=INF; 44 for(int i=1;i<m;i++){ 45 res=min(res,abs(a[1][i]-a[1][i+1])); 46 } 47 printf("%d ",res); 48 return 0; 49 } 50 for(int i=1;i<=n;i++){ 51 for(int j=1;j<=n;j++){ 52 if(i==j)continue; 53 Min[i][j]=INF; 54 for(int k=1;k<=m;k++){ 55 Min[i][j]=min(Min[i][j],abs(a[i][k]-a[j][k])); 56 } 57 } 58 } 59 60 int ans=0; 61 62 for(int i=1;i<=n;i++){ 63 for(int j=1;j<=n;j++){ 64 if(i==j)continue; 65 int res=INF; 66 for(int k=1;k<m;k++){ 67 res=min(res,abs(a[i][k]-a[j][k+1])); 68 } 69 if(m==1)res=INF; 70 memset(dp,-1,sizeof(dp)); 71 res=min(res,solve(i,j,0,i)); 72 ans=max(ans,res); 73 } 74 } 75 printf("%d ",ans); 76 return 0; 77 }
以上是关于Codeforces Round #531 (Div. 3)的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Round #531 (Div. 3)
Codeforces Round #436 E. Fire(背包dp+输出路径)
[ACM]Codeforces Round #534 (Div. 2)