A
签到(code不贴了)
PS:以后cf div2A(有时还有B)和atcoder <=200分(有时<=300)的题目不再贴code,不过可能也没几次比赛记录了。
B
高精度,枚举位数最短的可能,然后计算两个即可。
#include<bits/stdc++.h> using namespace std; const int N=1e5+7; struct node{int n,a[N];}ans,a,b; int n,mn; vector<int>G; char s[N]; bool check(node a,node b) { if(a.n!=b.n)return a.n<b.n; for(int i=a.n;i;i--) if(a.a[i]<b.a[i])return 1; else if(a.a[i]>b.a[i])return 0; return 0; } node operator+(node a,node b) { if(a.n<b.n)swap(a,b); for(int i=1;i<=a.n;i++) { a.a[i]+=b.a[i]; if(a.a[i]>=10)a.a[i]-=10,a.a[i+1]++; } if(a.a[a.n+1])a.n++; return a; } void split(int p) { a.n=p; for(int i=1;i<=p;i++)a.a[p-i+1]=s[i]-'0'; for(int i=p+1;i<N;i++)a.a[i]=0; b.n=n-p; for(int i=p+1;i<=n;i++)b.a[n-i+1]=s[i]-'0'; for(int i=n-p+1;i<N;i++)b.a[i]=0; a=a+b; if(check(a,ans))ans=a; } int main() { scanf("%d",&n); if(n==2){cin>>n,cout<<n/10+n%10;return 0;} scanf("%s",s+1); mn=n+2,ans.n=n+2; for(int i=1;i<n;i++) if(s[i+1]!='0') { int len=max(i,n-i); if(len<mn)mn=len,G.clear(),G.push_back(i); else if(len==mn)G.push_back(i); } for(int i=0;i<G.size();i++)split(G[i]); for(int i=ans.n;i;i--)printf("%d",ans.a[i]); }
C
太难了吧,简直被搞自闭了,WA了3发,主要是细节过多。实际上就是一个朴素O(nm)DP,f[i][j]表示以(i,j)为右下角的旗子个数,然后u[i][j]表示同色往上走的距离,注意第一段的距离是>=后面两端,而不是=,第二发这里WA了。第一发是只判了长度没判颜色。第三发是把长度都默认成1了。严重影响做题心态。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=1007; int n,m,u[N][N]; ll ans,f[N][N]; char a[N][N]; int check(int i,int j) { int len=u[i][j]; i-=u[i][j]; if(u[i][j]!=len)return 0; i-=u[i][j]; return len*(u[i][j]>=len); } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%s",a[i]+1); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(i==1||a[i][j]!=a[i-1][j])u[i][j]=1; else u[i][j]=u[i-1][j]+1; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { int v=check(i,j); if(!v)continue; f[i][j]=1; if(j>1&&v==check(i,j-1)&&a[i][j]==a[i][j-1]&&a[i-v][j]==a[i-v][j-1]&&a[i-2*v][j]==a[i-2*v][j-1])f[i][j]+=f[i][j-1]; ans+=f[i][j]; } cout<<ans; }
D
离线做法显然,把询问从小到大排序,然后扫的时候记录扫到了第几层(如果全部填满特判一下,很简单qwq),对于其余的次数,可以做一棵权值线段树。
其实这题真的可以加强,加强法是把n设为1e5,然后强制在线(讲真这是我第一想法,不过比较难写)。
#include<bits/stdc++.h> using namespace std; #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 typedef long long ll; const int N=5e5+7; struct node{ll x;int id;}q[N]; int n,m,Q,mx,ans[N],sum[N<<2],sz[N]; ll s[N]; vector<int>G[N]; bool cmp(node a,node b){return a.x<b.x;} void update(int k,int l,int r,int rt) { if(l==r){sum[rt]=1;return;} int mid=l+r>>1; if(k<=mid)update(k,lson);else update(k,rson); sum[rt]=sum[rt<<1]+sum[rt<<1|1]; } int query(int v,int l,int r,int rt) { if(l==r)return l; int mid=l+r>>1; if(v>sum[rt<<1])return query(v-sum[rt<<1],rson); return query(v,lson); } int main() { scanf("%d%d%d",&n,&m,&Q); for(int i=1,x;i<=n;i++)scanf("%d",&x),s[x]++,mx=max(mx,(int)s[x]); for(int i=1;i<=m;i++)G[s[i]].push_back(i); for(int i=1;i<=Q;i++)scanf("%I64d",&q[i].x),q[i].id=i,q[i].x-=n; sort(q+1,q+Q+1,cmp); for(int i=0;i<=mx;i++)sort(G[i].begin(),G[i].end()),s[i]=0; sz[0]=G[0].size();for(int i=1;i<=mx;i++)sz[i]=sz[i-1]+G[i].size(); s[0]=sz[0];for(int i=1;i<=mx;i++)s[i]=s[i-1]+sz[i]; for(int i=0;i<G[0].size();i++)update(G[0][i],1,m,1); for(int i=1,p=0;i<=Q;i++) if(s[mx]<q[i].x)ans[q[i].id]=(q[i].x-s[mx]-1)%m+1; else{ while(p<=mx&&s[p]<q[i].x) { p++; for(int i=0;i<G[p].size();i++)update(G[p][i],1,m,1); } if(p)q[i].x-=s[p-1]; ans[q[i].id]=query(q[i].x,1,m,1); } for(int i=1;i<=Q;i++)printf("%d ",ans[i]); }
E
咕。
result:rank37 rating+=157,毕竟这是我第4个号……