Codeforces Round #549题解
A题
计算每组最后出现的那个取min
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pll; typedef pair<int,int> plll; const int N=2e6+10; const int inf=0x3f3f3f3f; int a[N]; int main(){ ios::sync_with_stdio(false); int n; cin>>n; int i; for(i=1;i<=n;i++){ cin>>a[i]; } int cnt1=0,cnt2=0; for(i=1;i<=n;i++){ if(a[i]==1) cnt1=i; else cnt2=i; } cout<<min(cnt1,cnt2)<<endl; return 0; }
B题
这题有数位dp控制最高位那味,如果最高位不受限
那么后面全取9,因此对每一位都做一下这个判断即可
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pll; typedef pair<int,int> plll; const int N=2e6+10; const int inf=0x3f3f3f3f; int a[N]; ll pre[N]; int main(){ ios::sync_with_stdio(false); ll n; int i,j; cin>>n; int cnt=0; while(n){ a[++cnt]=n%10; n/=10; } if(cnt==1){ cout<<a[1]<<endl; return 0; } pre[0]=1; for(i=1;i<=20;i++){ pre[i]=pre[i-1]*9; } reverse(a+1,a+1+cnt); ll ans=1; ll mx=1; for(i=1;i<=cnt;i++){ ans=ans*a[i]; } for(i=1;i<=cnt;i++){ ll tmp=a[i]-1; if(a[i]==1){ tmp=1; } for(j=1;j<i;j++){ tmp*=a[j]; } for(j=i+1;j<=cnt;j++) tmp*=9; ans=max(ans,tmp); } cout<<ans<<endl; return 0; }
C题
过于水,记录三个数组判断一下就行
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pll; typedef pair<int,int> plll; const int N=2e6+10; const int inf=0x3f3f3f3f; int h[N],ne[N],e[N],idx; int in[N],num[N]; int vis[N]; void add(int a,int b){ } int main(){ ios::sync_with_stdio(false); int n; cin>>n; int i; for(i=1;i<=n;i++){ int a,b; cin>>a>>b; if(a==-1){ continue; } in[a]++; vis[i]=b; num[a]+=b; } int flag=0; for(i=1;i<=n;i++){ if(vis[i]&&(in[i]==num[i])){ cout<<i<<" "; flag=1; } } if(!flag){ cout<<-1; } cout<<endl; return 0; }
D题
起点在哪其实无所谓,那么我们假定0点为对于起点最近的那个,这样就有两种情况,一种是起点后a,一种是起点前a,那么对于b也是两种情况,不同的是,b可以是每个点的前后差值,因此枚举每种情况取最值即可
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pll; typedef pair<int,int> plll; const int N=2e6+10; const int inf=0x3f3f3f3f; ll gcd(ll a,ll b){ return b?gcd(b,a%b):a; } int main(){ ios::sync_with_stdio(false); ll n,k; ll a,b; cin>>n>>k>>a>>b; ll ans=0; ll res=1e18; ll tmpa=a; ll i; for(i=0;i<=(n-1)*k;i+=k){ ll tmpb=(i-b+n*k)%(n*k); ll d=(tmpb-tmpa+n*k)%(n*k); ans=max(ans,n*k/gcd(d,n*k)); res=min(res,n*k/gcd(d,n*k)); tmpb=(i+b+n*k)%(n*k); d=(tmpb-tmpa+n*k)%(n*k); ans=max(ans,n*k/gcd(d,n*k)); res=min(res,n*k/gcd(d,n*k)); } tmpa=(-a+n*k)%(n*k); for(i=0;i<=(n-1)*k;i+=k){ ll tmpb=(i-b+n*k)%(n*k); ll d=(tmpb-tmpa+n*k)%(n*k); ans=max(ans,n*k/gcd(d,n*k)); res=min(res,n*k/gcd(d,n*k)); tmpb=(i+b+n*k)%(n*k); d=(tmpb-tmpa+n*k)%(n*k); ans=max(ans,n*k/gcd(d,n*k)); res=min(res,n*k/gcd(d,n*k)); } cout<<res<<" "<<ans<<endl; return 0; }
E题
没有想到做法,没想到倍增的思路。
我们发现对于每个pi,前面的数都是固定的
因此我们对于ai,计算以他为结尾的序列,这样可以根据他最近的前面的那个数,用倍增的思路,计算他跳n-1次的最晚出现位置
这样再用一次倍增维护区间max,直接求解区间最值是否大于l即可
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pll; const int N=2e5+10; const int mod=998244353; const int inf=0x3f3f3f3f; int p[N],pre[N]; int a[N],lg[N]; int f[N][27]; int g[N][27]; int lst[N]; void init(){ lg[1]=0; lg[2]=1; for(int i=3;i<=200000;i++){ lg[i]=lg[i>>1]+1; } } int get(int l,int r){ int k=lg[r-l+1]; return max(g[l][k],g[r-(1<<k)+1][k]); } int main(){ ios::sync_with_stdio(false); int n,m,q; cin>>n>>m>>q; int i; init(); for(i=1;i<=n;i++){ cin>>p[i]; } for(i=1;i<=m;i++){ cin>>a[i]; } p[0]=p[n]; for(i=1;i<=n;i++){ pre[p[i]]=p[i-1]; } for(i=1;i<=m;i++){ f[i][0]=lst[pre[a[i]]]; lst[a[i]]=i; } for(i=1;i<=25;i++){ for(int j=1;j<=m;j++){ f[j][i]=f[f[j][i-1]][i-1]; } } for(i=1;i<=m;i++){ g[i][0]=i; for(int j=0;j<=lg[n-1];j++){ if((n-1)&(1<<j)){ g[i][0]=f[g[i][0]][j]; } } } for(i=1;i<=lg[m];i++){ for(int j=1;j+(1<<i)-1<=m;j++){ g[j][i]=max(g[j][i-1],g[j+(1<<i-1)][i-1]); } } string s=""; while(q--){ int l,r; cin>>l>>r; if(get(l,r)>=l){ s+='1'; } else{ s+='0'; } } cout<<s<<endl; }
没有人不辛苦,只有人不喊疼