比赛的时候E调了好久...F没时间写T T
A:直接走到短的路上来回走就好了
#include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<cmath> #include<algorithm> using namespace std; const int maxn=500010,inf=1e9; int n,a,b,c; inline void read(int &k) { int f=1;k=0;char c=getchar(); while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); while(c<='9'&&c>='0')k=k*10+c-'0',c=getchar(); k*=f; } int main() { read(n);read(a);read(b);read(c); if(n==1)return puts("0"),0; int mn=min(a,min(b,c));int now=1; if(a==mn||b==mn)printf("%d ",mn*(n-1)); else printf("%d ",min(a,b)+mn*(n-2)); }
B:将所有数%m,找到最多的相同的数即可
#include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<cmath> #include<algorithm> using namespace std; const int maxn=500010,inf=1e9; int n,k,m,ans,ansi,cntt; int x[maxn],y[maxn]; int v[maxn]; inline void read(int &k) { int f=1;k=0;char c=getchar(); while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); while(c<='9'&&c>='0')k=k*10+c-'0',c=getchar(); k*=f; } int main() { read(n);read(k);read(m); for(int i=1;i<=n;i++)read(x[i]),y[i]=x[i]%m; for(int i=1;i<=n;i++) { v[y[i]]++; if(v[y[i]]>ans) { ans=v[y[i]]; ansi=y[i]; } } if(ans>=k) { puts("Yes"); for(int i=1;i<=n;i++) { if(y[i]==ansi)printf("%d ",x[i]),cntt++; if(cntt==k)return 0; } } else puts("No"); }
C:答案只可能在[n-100,n]之间,枚举一下就好
#include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<cmath> #include<algorithm> using namespace std; const int maxn=500010,inf=1e9; int n,cnt; int ans[maxn]; inline void read(int &k) { int f=1;k=0;char c=getchar(); while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); while(c<='9'&&c>='0')k=k*10+c-'0',c=getchar(); k*=f; } int main() { read(n); for(int i=max(1,n-100);i<=n;i++) { int x=i,sum=i; while(x) { sum+=x%10; x/=10; } if(sum==n)ans[++cnt]=i; } printf("%d ",cnt); for(int i=1;i<=cnt;i++)printf("%d ",ans[i]); }
D:最后连续的硬币删掉,前面还剩多少个硬币就是答案
#include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<cmath> #include<algorithm> using namespace std; const int maxn=500010,inf=1e9; int n,x; bool b[maxn]; inline void read(int &k) { int f=1;k=0;char c=getchar(); while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); while(c<='9'&&c>='0')k=k*10+c-'0',c=getchar(); k*=f; } int main() { puts("1");read(n);int N=n; for(int i=1;i<=n;i++) { // printf("%dQAQ ",N); read(x);b[x]=1; while(b[N])N--; printf("%d ",i-(n-N)+1); } }
E:从每种数字可以改或者不改想到2-SAT,如果第i个字符串比第i+1个字符串小,v[i][j]和v[i+1][j]不一样,那么v[i+1][j]改,v[i][j]就必须改,v[i][j]不改,v[i+1][j]就不能改,如果第i个字符串比第i+1个字符串大,那么v[i][j]必须改,v[i+1][j]不能改,如上连边跑一个可行方案即可。
#include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<algorithm> #include<queue> #include<cmath> #include<map> #define ll long long using namespace std; const int maxn=200010,inf=1e9; struct poi{int too,pre,x;}e[maxn<<2],e2[maxn<<2]; int last[maxn],last2[maxn],dfn[maxn],low[maxn],col[maxn],lack[maxn],ru[maxn],rs[maxn],st[maxn],op[maxn]; int n,m,x,y,z,tot,tot2,tott,top,color,flag,len,cnt; int ans[maxn]; vector<int>v[maxn]; void read(int &k) { int f=1;k=0;char c=getchar(); while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); while(c<='9'&&c>='0')k=k*10+c-'0',c=getchar(); k*=f; } void add(int x,int y){e[++tot].too=y;e[tot].x=x;e[tot].pre=last[x];last[x]=tot;} void add2(int x,int y){e2[++tot2].too=y;e2[tot2].x=x;e2[tot2].pre=last2[x];last2[x]=tot2;} int next(int x){return x&1?x+1:x-1;} void tarjan(int x) { dfn[x]=low[x]=++tott;st[++top]=x;lack[x]=top; for(int i=last[x];i;i=e[i].pre) if(!dfn[e[i].too])tarjan(e[i].too),low[x]=min(low[x],low[e[i].too]); else if(!col[e[i].too])low[x]=min(low[x],dfn[e[i].too]); if(dfn[x]==low[x])for(color++;top>=lack[x];top--)col[st[top]]=color; } void topsort() { top=0;for(int i=1;i<=color;i++)if(!ru[i])st[++top]=i; while(top) { int now=st[top--]; if(!rs[now])rs[now]=1,rs[op[now]]=2; for(int i=last2[now];i;i=e2[i].pre) if(!(--ru[e2[i].too]))st[++top]=e2[i].too; } } int main() { read(n);read(m); for(int i=1;i<=n;i++) { read(len); for(int j=1;j<=len;j++) read(x),v[i].push_back(x); } for(int i=1;i<n;i++) { int flagg=0; for(int j=0;j<min(v[i].size(),v[i+1].size());j++) if(v[i][j]!=v[i+1][j]) { if(v[i][j]<v[i+1][j])add(next(v[i+1][j]<<1),next((v[i][j])<<1)),add(v[i][j]<<1,v[i+1][j]<<1); else add(v[i][j]<<1,next((v[i][j])<<1)),add(next((v[i+1][j])<<1),v[i+1][j]<<1); flagg=1;break; } if(!flagg&&v[i].size()>v[i+1].size())return puts("No"),0; // else add(next(v[i][min(v[i].size(),v[i+1].size())]<<1),next((v[i+1][min(v[i].size(),v[i+1].size())])<<1)); } for(int i=1;i<=m<<1;i++)if(!dfn[i])tarjan(i); for(int i=1;i<=m;i++) { if(col[i<<1]==col[next(i<<1)]){printf("No ");flag=1;break;} else op[col[i<<1]]=col[next(i<<1)],op[col[next(i<<1)]]=col[i<<1]; } if(flag)return 0; for(int i=1;i<=tot;i++)if(col[e[i].x]!=col[e[i].too])add2(col[e[i].too],col[e[i].x]),ru[col[e[i].x]]++; topsort(); // for(int i=1;i<=tot;i++)printf("QAQ%d %d ",e[i].x,e[i].too); //if(rs[col[(i<<1)]]==rs[col[next(i<<1)]])return puts("No"),0; for(int i=1;i<=m;i++)if(rs[col[(i<<1)]]!=1)ans[++cnt]=i; printf("Yes %d ",cnt); for(int i=1;i<=cnt;i++)printf("%d ",ans[i]); return 0; }
F:预处理出每个数每一位是0的那位左边最近的1和右边最近的1,用单调栈找出每个最大值所在的区间,统计答案即可。
T T一开始只预处理了20位查了好久错,浅谈状压写多了的后果
#include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<cmath> #include<algorithm> #define ll long long using namespace std; const int maxn=500010,inf=2e9; int n,top; int st[maxn],a[maxn],digit[maxn][32],pre[maxn][32],Pre[maxn],next[maxn][32],Next[maxn],cnt[maxn]; ll ans; inline void read(int &k) { int f=1;k=0;char c=getchar(); while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); while(c<='9'&&c>='0')k=k*10+c-'0',c=getchar(); k*=f; } int main() { read(n); for(int i=1;i<=n;i++) { read(a[i]); for(int x=a[i];x;x>>=1)digit[i][++cnt[i]]=x&1; } for(int j=1,last=0;j<=30;j++,last=0) for(int i=1;i<=n;i++) { if(!digit[i][j])pre[i][j]=last; if(digit[i][j])last=i; } for(int i=1;i<=n;i++) for(int j=1;j<=30;j++) if(!digit[i][j]) Pre[i]=max(Pre[i],pre[i][j]); memset(next,32,sizeof(next)); for(int j=1,last=n+1;j<=30;j++,last=n+1) for(int i=n;i;i--) { if(!digit[i][j])next[i][j]=last; if(digit[i][j])last=i; } memset(Next,32,sizeof(Next)); for(int i=1;i<=n;i++) for(int j=1;j<=30;j++) if(!digit[i][j]) Next[i]=min(Next[i],next[i][j]); a[++n]=inf; for(int i=1;i<=n;i++) { for(;top&&a[i]>=a[st[top]];top--) { ans+=1ll*((i-1)-st[top]+1)*(st[top]-(st[top-1]+1)+1); ans-=1ll*(1ll*st[top]-1ll*max(st[top-1]+1,Pre[st[top]]+1)+1)*(min(i-1,Next[st[top]]-1)-st[top]+1); } st[++top]=i; } printf("%lld ",ans); }