A:签到。
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; #define ll long long char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int T; int main() { /*#ifndef ONLINE_JUDGE freopen("a.in","r",stdin); freopen("a.out","w",stdout); #endif*/ T=read(); while (T--) { int n=read(),x=read(),y=read(),d=read(); if (abs(y-x)%d==0) cout<<abs(y-x)/d<<endl; else { int ans=2000000000; if ((y-1)%d==0) ans=min(ans,(y-1)/d+(x-2)/d+1); if ((n-y)%d==0) ans=min(ans,(n-y)/d+(n-x-1)/d+1); if (ans==2000000000) cout<<-1<<endl; else cout<<ans<<endl; } } return 0; }
B:讨论了好多种情况写的老长交了五发30min的时候才过心态爆炸。随便怎么做都行。
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; #define ll long long #define N 200010 char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int n,a[N],pre[N],suf[N],ans,cnt; int main() { /*#ifndef ONLINE_JUDGE freopen("a.in","r",stdin); freopen("a.out","w",stdout); #endif*/ n=read(); for (int i=1;i<=n;i++) cnt+=(a[i]=getc()=='S'); int x=0; for (int i=1;i<=n;i++) { pre[i]=x; if (a[i]) x=i; } x=n+1; for (int i=n;i>=1;i--) { suf[i]=x; if (a[i]) x=i; } int flag=0; for (int i=1;i<=n;i++) if (a[i]==0) { int t=i;while (t<n&&a[t+1]==a[i]) t++; flag++; i=t; } if (flag==0) {cout<<0;return 0;} if (flag==1) for (int i=1;i<=n;i++) if (a[i]==0) { int t=i;while (t<n&&a[t+1]==a[i]) t++; cout<<t-i+1;return 0; } for (int i=1;i<=n;i++) if (pre[i]!=i-1&&suf[i]!=i+1) ans=max(ans,suf[i]-pre[i]-1); if (flag<=2) ans--; if (flag>=2) for (int i=1;i<=n;i++) { if (pre[i]==i-1) ans=max(ans,suf[i]-i); if (suf[i]==i+1) ans=max(ans,i-pre[i]); } if (cnt==0) ans=n; cout<<max(0,ans)<<endl; return 0; }
C:对于每个科目显然应该从大到小选。枚举各科的学生人数,考虑每个科目,只要能选该科的人数足够且价值>0就应该把这些人选进去。用链表维护哪些科目是应该选的即可,只要人数不够或者价值<=0就将其从中删除。
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> #include<vector> using namespace std; #define ll long long #define N 200010 char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int n,m,ans,cnt,tot[N],cho[N],nxt[N],pre[N]; vector<int> a[N]; int main() { /*#ifndef ONLINE_JUDGE freopen("a.in","r",stdin); freopen("a.out","w",stdout); #endif*/ n=read(),m=read(); for (int i=1;i<=n;i++) { int x=read(),y=read(); a[x].push_back(y);tot[x]++; } for (int i=1;i<=m;i++) sort(a[i].begin(),a[i].end()),reverse(a[i].begin(),a[i].end()); for (int i=0;i<=m;i++) nxt[i]=i+1,pre[i+1]=i; for (int j=1;j<=n;j++) { int x=nxt[0]; while (x!=m+1) { if (tot[x]>=0) { if (tot[x]==0) nxt[pre[x]]=nxt[x],pre[nxt[x]]=pre[x],cnt-=cho[x],tot[x]=-1; else { tot[x]--,cnt+=a[x][j-1],cho[x]+=a[x][j-1]; if (cho[x]<=0) nxt[pre[x]]=nxt[x],pre[nxt[x]]=pre[x],cnt-=cho[x],tot[x]=-1; } } x=nxt[x]; } ans=max(ans,cnt); } cout<<ans; return 0; }
D:显然应该尽量让他形成一条链。只有度数<=1的点会对其造成影响。在链的两端至少各放一个度数<=1的点并将主链连起来然后瞎连即可。讨论一下一些特殊情况。
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; #define ll long long #define N 510 char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int n,a[N],b[N],cnt,t; bool flag[N]; struct data{int x,y; }edge[N]; int main() { /*#ifndef ONLINE_JUDGE freopen("a.in","r",stdin); freopen("a.out","w",stdout); #endif*/ n=read(); for (int i=1;i<=n;i++) { a[i]=read(); if (a[i]==1) b[++cnt]=i; else flag[i]=1; } if (cnt==0) { cout<<"YES"<<' '<<n-1<<endl; cout<<n-1<<endl; for (int i=1;i<n;i++) cout<<i<<' '<<i+1<<endl; return 0; } if (cnt==1) { if (b[1]==1) { cout<<"YES"<<' '<<n-1<<endl; cout<<n-1<<endl; for (int i=1;i<n;i++) cout<<i<<' '<<i+1<<endl; } else { cout<<"YES"<<' '<<n-1<<endl; cout<<n-1<<endl; for (int i=1;i<b[1]-1;i++) cout<<i<<' '<<i+1<<endl; cout<<1<<' '<<b[1]<<endl; for (int i=b[1];i<n;i++) cout<<i<<' '<<i+1<<endl; } return 0; } if (n==2&&cnt==2) {cout<<"YES"<<' '<<1<<endl<<1<<endl<<1<<' '<<2;return 0;} for (int i=1;i<=n;i++) if (a[i]!=1) {edge[++t].x=b[1],edge[t].y=i;break;} if (t==0) {cout<<"NO";return 0;} for (int i=n;i>=1;i--) if (a[i]!=1) {edge[++t].x=b[cnt],edge[t].y=i;break;} if (t==1) {cout<<"NO";return 0;} int x=2;cnt--; for (int i=1;i<=n;i++) while (a[i]>2&&x<=cnt) edge[++t].x=b[x++],edge[t].y=i,a[i]--; for (int i=1;i<=n;i++) if (flag[i]) for (int j=i-1;j>=1;j--) if (flag[j]) {edge[++t].x=i,edge[t].y=j;break;} if (t<n-1) cout<<"NO"; else { cout<<"YES"<<' '<<n-cnt<<endl; cout<<n-1<<endl; for (int i=1;i<n;i++) cout<<edge[i].x<<' '<<edge[i].y<<endl; } return 0; }
E:先把本来就和C相同的数数出来做个前缀和。显然让所选区间的左右端点变为与C相同是不会更劣的。考虑每一种数。假设固定了左端点,右端点不断向右扩展,那么遇到与左端点相同的数就可以使答案+1,遇到本身就与C相同的数则会使答案-1。于是将对该数每一段的价值取出来,形如1 -a1 1 -a2 1……,做个最大子段和就可以了。
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; #define ll long long #define N 2000010 char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int n,m,a[N],p[N],sum[N],nxt[N],b[N],t,cnt,ans; int main() { /*#ifndef ONLINE_JUDGE freopen("a.in","r",stdin); freopen("a.out","w",stdout); #endif*/ n=read(),m=read(); for (int i=1;i<=n;i++) { a[i]=read()-m+1000000; if (a[i]==1000000) cnt++; } for (int i=1;i<=n;i++) nxt[i]=p[a[i]],p[a[i]]=i; for (int i=1;i<=n;i++) sum[i]=sum[i-1]+(a[i]==1000000); ans=cnt; for (int i=0;i<=2000000;i++) if (i!=1000000&&p[i]) { int x=p[i];t=0;b[++t]=1; while (nxt[x]) { b[++t]=sum[nxt[x]]-sum[x]; b[++t]=1; x=nxt[x]; } int s=0; for (int j=1;j<=t;j++) { s+=b[j]; if (s<0) s=0; ans=max(ans,cnt+s); } } cout<<ans<<endl; return 0; }
F:没看
G:最大权闭合子图裸题。
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; #define ll long long #define int long long #define N 2010 #define M 10010 #define S 0 #define T 2001 #define inf 10000000000000ll char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int n,m,p[N],a[N],t=-1,d[M],cur[M],q[M],ans; struct data{int to,nxt,cap,flow; }edge[M<<3]; void addedge(int x,int y,int z) { t++;edge[t].to=y,edge[t].nxt=p[x],edge[t].cap=z,edge[t].flow=0,p[x]=t; t++;edge[t].to=x,edge[t].nxt=p[y],edge[t].cap=0,edge[t].flow=0,p[y]=t; } bool bfs() { memset(d,255,sizeof(d));d[S]=0; int head=0,tail=1;q[1]=S; do { int x=q[++head]; for (int i=p[x];~i;i=edge[i].nxt) if (d[edge[i].to]==-1&&edge[i].flow<edge[i].cap) { q[++tail]=edge[i].to; d[edge[i].to]=d[x]+1; } }while (head<tail); return ~d[T]; } int work(int k,int f) { if (k==T) return f; int used=0; for (int i=cur[k];~i;i=edge[i].nxt) if (d[k]+1==d[edge[i].to]) { int w=work(edge[i].to,min(f-used,edge[i].cap-edge[i].flow)); edge[i].flow+=w,edge[i^1].flow-=w; if (edge[i].flow<edge[i].cap) cur[k]=i; used+=w;if (used==f) return f; } if (used==0) d[k]=-1; return used; } void dinic() { while (bfs()) { memcpy(cur,p,sizeof(p)); ans-=work(S,inf); } } signed main() { /*#ifndef ONLINE_JUDGE freopen("a.in","r",stdin); freopen("a.out","w",stdout); #endif*/ n=read(),m=read(); for (int i=1;i<=n;i++) a[i]=read(); memset(p,255,sizeof(p)); for (int i=1;i<=m;i++) { int x=read(),y=read(),z=read(); addedge(n+i,x,inf),addedge(n+i,y,inf); addedge(S,n+i,z);ans+=z; } for (int i=1;i<=n;i++) addedge(i,T,a[i]); dinic(); cout<<ans; return 0; }
小号打的。result: rank 34 rating +158