Codeforces Round #661 (Div. 3)(A B C D E)
rank: 974
rating: 1503 + 42
A:Remove Smallest
代码:
1 #include<bits/stdc++.h> 2 #define ll long long 3 #define MOD 998244353 4 #define INF 0x3f3f3f3f 5 #define mem(a,x) memset(a,x,sizeof(a)) 6 #define _for(i,a,b) for(int i=a; i< b; i++) 7 #define _rep(i,a,b) for(int i=a; i<=b; i++) 8 #define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); 9 using namespace std; 10 11 int main() 12 { 13 int n,t; 14 int a[105]; 15 cin>>t; 16 while(t--){ 17 cin>>n; 18 for(int i=1;i<=n;i++){ 19 scanf("%d",&a[i]); 20 } 21 sort(a+1,a+n+1); 22 int k=1; 23 for(int i=1;i<n;i++){ 24 if(a[i+1]-a[i]>1){ 25 k=0; 26 break; 27 } 28 } 29 if(k){ 30 cout<<"YES"<<endl; 31 }else{ 32 cout<<"NO"<<endl; 33 } 34 } 35 return 0; 36 }
B:Gifts Fixing
思路:找到A和B序列中的最小值,对于每个a[i]和b[i],贡献是max(a[i]-mina,b[i]-minb)。
代码:
1 #include<bits/stdc++.h> 2 #define ll long long 3 #define MOD 998244353 4 #define INF 0x3f3f3f3f 5 #define mem(a,x) memset(a,x,sizeof(a)) 6 #define _for(i,a,b) for(int i=a; i< b; i++) 7 #define _rep(i,a,b) for(int i=a; i<=b; i++) 8 #define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); 9 using namespace std; 10 11 ll a[105]; 12 ll b[105]; 13 int main() 14 { 15 int n,t; 16 cin>>t; 17 while(t--){ 18 cin>>n; 19 ll mina=1000000005; 20 ll minb=1000000005; 21 for(int i=1;i<=n;i++){ 22 scanf("%lld",&a[i]); 23 mina=min(a[i],mina); 24 } 25 for(int i=1;i<=n;i++){ 26 scanf("%lld",&b[i]); 27 minb=min(b[i],minb); 28 } 29 ll sum=0; 30 for(int i=1;i<=n;i++){ 31 ll da=a[i]-mina; 32 ll db=b[i]-minb; 33 ll xx=min(da,db); 34 sum+=xx; 35 da-=xx; 36 db-=xx; 37 //cout<<da<<" "<<db<<endl; 38 if(da!=0){ 39 sum+=da; 40 }else{ 41 sum+=db; 42 } 43 } 44 cout<<sum<<endl; 45 } 46 return 0; 47 }
C: Boats Competition
思路:就是暴力枚举每种可能重量下的最大值。
代码:
1 #include<bits/stdc++.h> 2 #define ll long long 3 #define MOD 998244353 4 #define INF 0x3f3f3f3f 5 #define mem(a,x) memset(a,x,sizeof(a)) 6 #define _for(i,a,b) for(int i=a; i< b; i++) 7 #define _rep(i,a,b) for(int i=a; i<=b; i++) 8 #define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); 9 using namespace std; 10 11 int w[1005]; 12 int sum[1005]; 13 int main() 14 { 15 int n,t; 16 cin>>t; 17 while(t--){ 18 cin>>n; 19 mem(sum,0); 20 for(int i=1;i<=n;i++){ 21 scanf("%d",&w[i]); 22 } 23 sort(w+1,w+n+1); 24 int num=0; 25 for(int i=w[n]+w[n-1];i>=w[1]+w[2];i--){ 26 int pp=0; 27 mem(sum,0); 28 for(int j=1;j<=n;j++){ 29 sum[w[j]]++; 30 } 31 for(int j=1;j<=n;j++){ 32 if(i-w[j]>=1){ 33 if((sum[i-w[j]]>=1&&w[j]!=i-w[j]&&sum[w[j]]>=1)||(sum[i-w[j]]>=2&&w[j]==i-w[j])){ 34 pp++; 35 sum[w[j]]--; 36 sum[i-w[j]]--; 37 } 38 } 39 } 40 //cout<<i<<" "<<pp<<endl; 41 num=max(num,pp); 42 } 43 cout<<num<<endl; 44 } 45 return 0; 46 }
D:Binary String To Subsequences
思路:贪心。如果当前位置为 1 ,找前面已经是否存在结尾是 0 的子串,如果不存在则增加子串序号。用 k0 和 k1两个vector 储存结尾是0 和 1 两种情况的子串编号,即如果没有这种情况的子串,则增加子串,否则就把这个字符加入一个已有的子串。
代码:
1 #include<bits/stdc++.h> 2 #define ll long long 3 #define MOD 998244353 4 #define INF 0x3f3f3f3f 5 #define mem(a,x) memset(a,x,sizeof(a)) 6 #define _for(i,a,b) for(int i=a; i< b; i++) 7 #define _rep(i,a,b) for(int i=a; i<=b; i++) 8 #define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); 9 using namespace std; 10 11 string s; 12 int a[200005]; 13 int k[200005]; 14 int main() 15 { 16 int n,t; 17 cin>>t; 18 while(t--){ 19 cin>>n; 20 cin>>s; 21 vector<int>k1; 22 vector<int>k0; 23 k1.clear(); 24 k0.clear(); 25 int num=1; 26 a[0]=1; 27 if(s[0]=='1'){ 28 k1.push_back(1); 29 }else{ 30 k0.push_back(1); 31 } 32 for(int i=1;i<s.size();i++){ 33 if(s[i]=='1'){ 34 if(k0.size()){ 35 a[i]=k0[0]; 36 k1.push_back(k0[0]); 37 k0.erase(k0.begin()); 38 }else{ 39 num++; 40 a[i]=num; 41 k1.push_back(num); 42 } 43 }else{ 44 if(k1.size()){ 45 a[i]=k1[0]; 46 k0.push_back(k1[0]); 47 k1.erase(k1.begin()); 48 }else{ 49 num++; 50 a[i]=num; 51 k0.push_back(num); 52 } 53 } 54 } 55 cout<<num<<endl; 56 for(int i=0;i<s.size();i++){ 57 if(i==s.size()-1){ 58 cout<<a[i]<<endl; 59 }else{ 60 cout<<a[i]<<" "; 61 } 62 } 63 } 64 return 0; 65 }
E1. Weights Division (easy version)
题意:给你一棵树,树的每条边都有权值,设这棵树的重量是从根走向每片叶子所获得的权值的总和。给你一个值S,你可以对任意一条路径操作,是的这条路径的权值 w[ i ] = w[ i ] /2 (向下取整)。问你最少需要几步操作就可以让树的重量小于等于S。
思路:贪心。一开始树的重量是确定的,就是每条边和该边使用次数的乘积之和。所以我们首先要计算出所有边的使用次数,我们用cnt 来表示。我们可以用 dfs 预处理每条边的使用次数。然后把对每条边的操作时的改变量放入一个 set 中,由于set 有自动排序功能,因此每一步操作只需要把set 末尾的元素删去,再用sum 减去这个值,然后再插入 某个w[ i ]更新后的值,这样可以使每次减去的数最大,也就可以使步数最少。
代码:
1 #include<bits/stdc++.h> 2 #define ll long long 3 #define MOD 998244353 4 #define INF 0x3f3f3f3f 5 #define mem(a,x) memset(a,x,sizeof(a)) 6 #define _for(i,a,b) for(int i=a; i< b; i++) 7 #define _rep(i,a,b) for(int i=a; i<=b; i++) 8 #define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); 9 using namespace std; 10 11 int w[100005]; 12 int cnt[100005]; 13 vector<pair<int,int>>g[100005]; 14 int n; 15 ll s; 16 void dfs(int x,int fa) 17 { 18 if(g[x].size()==1){ 19 cnt[fa]=1; 20 } 21 for(auto [to,id]:g[x]){ 22 if(id==fa)continue; 23 dfs(to,id); 24 if(fa!=-1)cnt[fa]+=cnt[id]; 25 } 26 } 27 ll getnum(int id) 28 { 29 return (ll)w[id]*cnt[id]-(ll)(w[id]/2)*cnt[id]; 30 } 31 int main() 32 { 33 int t; 34 cin>>t; 35 while(t--){ 36 mem(cnt,0); 37 mem(w,0); 38 scanf("%d %lld",&n,&s); 39 for(int i=0;i<=n;i++){ 40 g[i].clear(); 41 } 42 for(int i=0;i<n-1;i++){ 43 int x,y; 44 cin>>x>>y>>w[i]; 45 x--; 46 y--; 47 g[x].push_back({y,i}); 48 g[y].push_back({x,i}); 49 } 50 dfs(0,-1); 51 set<pair<ll,int>>st; 52 st.clear(); 53 ll sum=0; 54 for(int i=0;i<n-1;i++){ 55 long long num=(ll)w[i]*(ll)cnt[i]; 56 st.insert({getnum(i),i}); 57 sum+=num; 58 } 59 int step=0; 60 while(s<sum){ 61 int id=st.rbegin()->second; 62 sum-=getnum(id); 63 set<pair<ll,int> >::iterator ip; 64 ip=st.end(); 65 st.erase(--ip); 66 w[id]=w[id]/2; 67 st.insert({getnum(id),id}); 68 step++; 69 } 70 cout<<step<<endl; 71 } 72 return 0; 73 }
E2:0
F:0
越自律,越自由