A

模拟
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| #include<bits/stdc++.h> using namespace std; using i64=long long; const int N=2e5+10;
void solve(){ int cnt[27]={0}; int n;cin>>n; string s;cin>>s; for(int i=0;i<s.size();i++){ cnt[s[i]-'A'+1]++; } int ans=0; for(int i=1;i<=26;i++){{ if(cnt[i]>=i)ans++; } } cout<<ans<<'\n'; } int main(){ ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); int _;cin>>_; while(_--)solve(); return 0; }
|
B

构造一个先升后降的序列即可,也就是先从n-k输出到n再输出k-1到1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| #include<bits/stdc++.h> using namespace std; using i64=long long; const int N=2e5+10;
void solve(){ int n,k;cin>>n>>k; for(int i=n-k;i<=n;i++){ cout<<i<<' '; } for(int i=n-k-1;i>=1;i--) { cout<<i<<' '; } cout<<'\n'; } int main(){ ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); int _;cin>>_; while(_--)solve(); return 0; }
|
C

当我们需要选出k个任务的时候,就是枚举i从1-k分别作为选择a数组和b数组的数目,a数组用一个前缀和维护,b只用记录最大值
需要注意的是枚举的时候k可能大于n,分类讨论或者取min都可以
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| #include<bits/stdc++.h> using namespace std; using i64=long long; const int N=2e5+10;
void solve(){ i64 n,k;cin>>n>>k; int a[N]={0},b[N]={0}; for(int i=1;i<=n;i++)cin>>a[i]; for(int i=1;i<=n;i++)cin>>b[i]; i64 ans=0,sum=0; int mx=0; for(int i=1;(i<=n)&&(i<=k);i++){ sum+=a[i]; mx=max(b[i],mx); ans=max(ans,sum+1ll*mx*(k-i)); } cout<<ans<<'\n'; } int main(){ ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); int _;cin>>_; while(_--)solve(); return 0; }
|
D

我用的是结构体,然后排序选前三个讨论,相同就跳过,因为三天最多只会选到某个的第三大
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| #include<bits/stdc++.h> using namespace std; using i64=long long; const int N=2e5+10; void solve(){ int n;cin>>n; vector<pair<int,int>>v1; vector<pair<int,int>>v2; vector<pair<int,int>>v3; for(int i=1;i<=n;i++){ int x;cin>>x; v1.push_back(make_pair(x,i)); } for(int i=1;i<=n;i++){ int x;cin>>x; v2.push_back(make_pair(x,i)); } for(int i=1;i<=n;i++){ int x;cin>>x; v3.push_back(make_pair(x,i)); } int ans=0; sort(v1.begin(),v1.end()); sort(v2.begin(),v2.end()); sort(v3.begin(),v3.end()); for(int i=n-1;i>=n-3;i--){ for(int j=n-1;j>=n-3;j--){ for(int k=n-1;k>=n-3;k--){ if(v2[j].second==v3[k].second||v1[i].second==v2[j].second||v1[i].second==v3[k].second)continue; ans=max(ans,v1[i].first+v2[j].first+v3[k].first); } } } cout<<ans<<'\n'; } int main(){ ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); int _;cin>>_; while(_--)solve(); return 0; }
|
E

这里我就写E1和E2的通解了,因为E1和E2只有数据范围不同。
这道题还是很有意思的,我们先思考一下什么样的颜色的弹珠会被先选
在自己的回合,我们想要消去弹珠的差距。
我们就是在想保有自己最多的情况下还要消去对面的最多,也就是自己的x和对面的y最好都很大,所以就按x+y排序就好
然后模拟按分别取的得分获得结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| #include<bits/stdc++.h> using namespace std; using i64=long long; const int N=2e5+10;
void solve(){ int n;cin>>n; vector<int>a(n); vector<int>b(n); vector<int>c(n); for(int i=0;i<n;i++)cin>>a[i]; for(int i=0;i<n;i++)cin>>b[i]; iota(c.begin(),c.end(),0); sort(c.begin(),c.end(),[&](int x,int y){ return a[x]+b[x]>a[y]+b[y]; } ); i64 ans=0; bool turn=true; for(auto &i:c){ if(turn){ ans+=a[i]-1; }else{ ans-=b[i]-1; } turn^=1; } cout<<ans<<'\n'; } int main(){ ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); int _;cin>>_; while(_--)solve(); return 0; }
|