codeforce 构造题专练
1.https://codeforces.com/contest/1746/problem/A
题意:给定一组数,满足由0,1构成,可以进行这样的操作来实现将数组a变成只有一个元素1的数组的最小操作数
操作如下:
一、选相邻两个元素的最小值并将他们合并,数组长度长度减一
二、选择连续k个元素求他们最大值并合并,数组长度减k-1
做法:很水,一次A
从前往后扫如果发现是1就标记并跳出
最后根据标记输出就可以了
参考代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define int long long 4 #define IOS ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0); 5 vector<int>q; 6 int t; 7 void solved() 8 { 9 q.clear(); 10 int n,k; 11 cin>>n>>k; 12 int tmp; 13 for(int i=0;i<n;i++) 14 { 15 cin>>tmp; 16 q.push_back(tmp); 17 } 18 bool flag=false; 19 for(int i=0;i<q.size();i++) 20 { 21 if(q[i]==1) 22 { 23 flag=true; 24 break; 25 } 26 /*else 27 { 28 flag=false; 29 }*/ 30 } 31 /*for(int i=0;i<q.size();i++) 32 { 33 cout<<q[i]<<" "; 34 }* 35 cout<<endl;*/ 36 if(flag) 37 { 38 cout<<"YES"<<endl; 39 } 40 else 41 { 42 cout<<"NO"<<endl; 43 } 44 } 45 signed main() 46 { 47 IOS; 48 cin>>t; 49 while(t--) 50 { 51 solved(); 52 } 53 }
2.https://codeforces.com/contest/1743/problem/C
题意:给定一组数来表示杂志,并且有些杂志盖了盖子有些杂志没盖,遇到了下雨天,你可以选择相邻的有盖的杂志来盖住无盖的杂志以获得最大价值杂志
为可以获得的最大杂志是多少
做法:
第一次在cf上做出dp,用dp[i][0/1]来表示第i个杂志(盖盖子/不盖)的最大价值,
如果碰到有盖子的,转移方程是max(dp[i-1][0],dp[i-1][1])+a[i]即用前面状态加上当前值
如果无盖,max(dp[i-1][0],dp[i-1][1])就是前一个有盖子和无盖子的最大价值
最后输出有盖子的和无盖子的n谁更大就好了
参考代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define int long long 4 #define IOS ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0); 5 string s; 6 const int N=2e5+10; 7 int t; 8 int n; 9 /*struct node 10 { 11 int w; 12 char c; 13 }a[N];*/ 14 int a[N]; 15 int dp[N][2]; 16 void solved() 17 { 18 memset(dp,0,sizeof(dp)); 19 cin>>n; 20 cin>>s; 21 s=" "+s; 22 for(int i=1;i<=n;i++) 23 { 24 cin>>a[i]; 25 } 26 for(int i=1;i<=n;i++) 27 { 28 if(s[i]=='1') 29 { 30 dp[i][1]=max(dp[i-1][0],dp[i-1][1])+a[i]; 31 dp[i][0]=dp[i-1][0]+a[i-1]; 32 } 33 else 34 { 35 dp[i][0]=max(dp[i-1][0],dp[i-1][1]); 36 } 37 } 38 int ans=max(dp[n][0],dp[n][1]); 39 cout<<ans<<endl; 40 } 41 signed main() 42 { 43 IOS; 44 cin>>t; 45 while(t--) 46 { 47 solved(); 48 } 49 return 0; 50 }
3.https://codeforces.com/contest/1746/problem/B
题意:给定一组数,由0,1构成,要求进行这样的操作来实现数组满足非递减的排列
操作如下:
1.将ai加到aj上,数组长度减一
2.将ai从数组里面移除,数组长度减一
做法:
双指针枚举,定义首指针和尾指针,分别表示0和1的个数,最终实现两者个数相等即可
参考代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define int long long 4 #define IOS ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0); 5 const int N=1e5+10; 6 int t; 7 int n; 8 int a[N]; 9 //就是从后向前扫,有空白就用后面没扫过的 1 来补上,统计答案即可 10 void solved() 11 { 12 bool flag=false; 13 int cnt=0; 14 int ans=0; 15 cin>>n; 16 for(int i=1;i<=n;i++) 17 { 18 cin>>a[i]; 19 cnt+=a[i]; 20 } 21 if(is_sorted(a+1,a+1+n)) 22 { 23 cout<<0<<endl; 24 return ; 25 } 26 /*for(int i=1;i<=n;i++) 27 { 28 /*if(a[i]==1) 29 { 30 a[n]+=a[i]; 31 a[i]=0; 32 cnt++; 33 } 34 */ 35 /*for(int j=i+1;j<=n;j++) 36 { 37 if(a[j]==0) 38 { 39 a[j]=a[i]; 40 a[i]=0; 41 cnt++; 42 } 43 } 44 if(is_sorted(a+1,a+1+n)) 45 { 46 cout<<cnt<<endl; 47 return ; 48 } 49 }*/ 50 //cout<<cnt<<endl; 51 for(int i=n;i>=1;i--) 52 { 53 if(ans==cnt) 54 { 55 break; 56 } 57 if(!a[i]) 58 { 59 ans++; 60 } 61 if(a[i]) 62 cnt--; 63 /*if(ans==cnt) 64 { 65 break; 66 }*/ 67 } 68 cout<<ans<<endl; 69 } 70 signed main() 71 { 72 IOS; 73 cin>>t; 74 while(t--) 75 { 76 solved(); 77 } 78 return 0; 79 }
还有一种很巧的做法,是看的别人的思路,也可以实现:
将数组进行排序并且与原数组比较每一位如果有不同的cnt++;
最后输出cnt/2
参考代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define int long long 4 #define IOS ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0); 5 const int N=1e5+10; 6 int t; 7 int n; 8 int a[N]; 9 int b[N]; 10 void solved() 11 { 12 int cnt=0; 13 cin>>n; 14 for(int i=1;i<=n;i++) 15 { 16 cin>>a[i]; 17 b[i]=a[i]; 18 } 19 sort(b+1,b+1+n); 20 for(int i=1;i<=n;i++) 21 { 22 if(b[i]!=a[i]) 23 cnt++; 24 } 25 cout<<cnt/2<<endl; 26 } 27 signed main() 28 { 29 IOS; 30 cin>>t; 31 while(t--) 32 { 33 solved(); 34 } 35 return 0; 36 }
本文来自博客园,作者:江上舟摇,转载请注明原文链接:https://www.cnblogs.com/LQS-blog/p/16826464.html