Codeforces Round 961 (Div. 2)
A
#include<bits/stdc++.h> using namespace std; int a[200]; void solve(){ int n,k;cin>>n>>k; a[1]=n; for(int j=n-1,i=2;i<=1+(n-1)*2;i+=2,j--){ a[i]=a[i+1]=j; } if(!k){ cout<<0<<"\n"; return; } for(int i=1;i<=1+(n-1)*2;i++){ k-=a[i]; if(k<=0) { cout<<i<<"\n"; return ; } } } int main(){ ios_base::sync_with_stdio(false); cin.tie(0);cout.tie(0); int t;cin>>t; while(t--){ //TODO solve(); } }
B1
考虑双指针,固定左端点 l 然后维护最大的右端点 r 使得 a[r]-a[l]<=1 ,且能凑的花瓣数尽量多。
但是特判没写好,双指针寄了,最后先过了B2,改的B2代码过的B1
B2
考虑都买第一种,剩下的钱再买第二种,还有剩的话考虑加钱把之前买的第一种看能不能升级成第二种(价格只差1,且收益和价格一样,相当于在原来的基础上多花一块钱就能多拿一个花瓣)
#include<bits/stdc++.h> using namespace std; const int N = 2e5+5; #define int long long struct node{ int v,num; }a[N]; bool cmp(node a,node b){ return a.v<b.v; } void solve(){ int n,m;cin>>n>>m; for(int i=1;i<=n;i++) cin>>a[i].v; for(int i=1;i<=n;i++) cin>>a[i].num; sort(a+1,a+n+1,cmp); int ans=0; for(int i=1;i<=n-1;i++){ int t1=m/a[i].v; t1=min(t1,a[i].num); ans=max(ans,t1*a[i].v); if(a[i+1].v!=a[i].v+1) continue; int left=m-t1*a[i].v; int t2=left/a[i+1].v; t2=min(t2,a[i+1].num); ans=max(ans,t1*a[i].v+t2*a[i+1].v); left-=t2*a[i+1].v; if(left && t2<a[i+1].num ){ int add=a[i+1].num-t2; add=min(add,min(t1,left)); ans=max(ans,t1*a[i].v+t2*a[i+1].v+add); } } int t1=m/a[n].v; t1=min(t1,a[n].num); ans=max(ans,t1*a[n].v); cout<<ans<<"\n"; // spj n } // 1 1 1 2 4 5 6 7 signed main(){ ios_base::sync_with_stdio(false); cin.tie(0);cout.tie(0); int t;cin>>t; while(t--){ //TODO solve(); } }
C
有人说是典中典,可能做题太少了没见过类似的,觉得还挺有意思。
首先不能暴力扩大,数值很快就爆炸了(实测8 7 6 5 4 3 2 1寄得飞快)
第一次想到了取对数后得到
(偷了其他博主的图)
但是这个式子还是不会处理,没想到再取一次对数变成
然后换了思路,不能维护真实数值的话显然要从原本的值入手
维护一个cnt数组,cnt[i]表示a[i]平方了几次。
考虑 a[i] < a[i-1] ,显然a[i]的大小要先大于等于a[i] ,这个可以暴力求
然后a[i-1]做了cnt[i-1]次,a[i] 也要跟着做cnt[i-1] 次
a[i]>a[i-1]同理 ,讨论下此时a[i-1]的真实值是否大于a[i] ,若没有大于则不管
若大于了则a[i]也要一起做cnt[i-1]次,但又因为a[i]的初值比a[i-1]大,所以还要扣掉这部分
具体细节见代码
#include<bits/stdc++.h> using namespace std; const int N =2e5+5; #define int long long int a[N],cnt[N],b[N]; void solve(){ int n;cin>>n; for(int i=1;i<=n;i++) cin>>a[i],cnt[i]=0; int ans=0; for(int i=2;i<=n;i++){ if(a[i]<a[i-1]){ if(a[i]==1) { cout<<-1<<"\n"; return; } cnt[i]=cnt[i-1]; int tot=0; int tmp=a[i]; while(tmp<a[i-1]){ tmp=tmp*tmp; tot++; } cnt[i]+=tot; } else { if(a[i]==a[i-1]) { cnt[i]=cnt[i-1]; } else { // a[i]>a[i-1] int need=0,c=a[i-1],d=a[i]; if(c==1) continue; while( c<d ){ c=c*c; need++; } //cout<<i<<" :: "<<c<<" "<<d<<" "<<cnt[i-1]<<"\n"; if(c==d){ if(need<=cnt[i-1]) { // a[i] > a[i-1] cnt[i]=cnt[i-1]-need; } else cnt[i]=0; } else if(c>d){ if(need<=cnt[i-1]) { // a[i] > a[i-1] cnt[i]=1+cnt[i-1]-need; } else cnt[i]=0; } } } } for(int i=1;i<=n;i++){ ans+=cnt[i]; } cout<<ans<<"\n"; } signed main(){ ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0); int t;cin>>t; while(t--){ //TODO solve(); } }