The 17th Zhejiang Provincial Collegiate Programming Contest
题解:
https://files.cnblogs.com/files/clrs97/ZJCPC2020analyze.zip
Code:(Part)
A. AD 2020
#include<cstdio> int f[10005][13][33],is[10005][13][33],i,j,lim,k,sum,A,B,C,D,E,F,ans,Case; inline int have(int x,int y){ if(y==1||y==3||y==5||y==7||y==8||y==10||y==12)return 31; if(y==4||y==6||y==9||y==11)return 30; if(x%400==0)return 29; if(x%100==0)return 28; if(x%4==0)return 29; return 28; } inline bool check(int x,int y,int z){ static int s[9]; s[1]=x/1000; s[2]=x/100%10; s[3]=x/10%10; s[4]=x%10; s[5]=y/10; s[6]=y%10; s[7]=z/10; s[8]=z%10; for(int i=1;i<=7;i++)if(s[i]==2&&s[i+1]==0&&s[i+2]==2)return 1; return 0; } int main(){ for(i=2000;i<=9999;i++)for(j=1;j<=12;j++){ lim=have(i,j); for(k=1;k<=lim;k++){ if(check(i,j,k)){ sum++; is[i][j][k]=1; } f[i][j][k]=sum; } } scanf("%d",&Case); while(Case--){ scanf("%d%d%d%d%d%d",&A,&B,&C,&D,&E,&F); ans=f[D][E][F]-f[A][B][C]+is[A][B][C]; printf("%d\n",ans); } }
B. Bin Packing Problem
#include<cstdio> #include<map> #include<algorithm> using namespace std; const int M=2333333; int Case,n,m,i,x,ff,bf,v[M];map<int,int>T; void build(int x,int a,int b){ v[x]=m; if(a==b)return; int mid=(a+b)>>1; build(x<<1,a,mid),build(x<<1|1,mid+1,b); } inline void FF(int p){ int x=1,a=1,b=n,mid; while(a<b){ mid=(a+b)>>1; if(v[x<<=1]>=p)b=mid;else a=mid+1,x++; } if(v[x]==m)ff++; v[x]-=p; for(x>>=1;x;x>>=1)v[x]=max(v[x<<1],v[x<<1|1]); } inline void BF(int x){ map<int,int>::iterator it=T.lower_bound(x); if(it==T.end()){ bf++; if(x<m)T[m-x]++; }else{ int o=it->first; T[o]--; if(!T[o])T.erase(o); if(x<o)T[o-x]++; } } int main(){ scanf("%d",&Case); while(Case--){ scanf("%d%d",&n,&m); build(1,1,n); ff=bf=0; T.clear(); for(i=1;i<=n;i++)scanf("%d",&x),FF(x),BF(x); printf("%d %d\n",ff,bf); } }
C. Crossword Validation
#include<cstdio> #include<cstring> typedef long long ll; const int N=1005,M=4000005; int Case,n,m,i,j,k,len,x,o,w,son[M][26],v[M],tot;char a[N][N],s[M]; inline ll solve(){ ll ans=0; for(i=1;i<=n;i++)for(j=1;j<=n;){ if(a[i][j]=='#'){ j++; continue; } for(x=1;j<=n&&a[i][j]!='#';j++)x=son[x][a[i][j]-'a']; if(!v[x])return -1; ans+=v[x]; } for(i=1;i<=n;i++)for(j=1;j<=n;){ if(a[j][i]=='#'){ j++; continue; } for(x=1;j<=n&&a[j][i]!='#';j++)x=son[x][a[j][i]-'a']; if(!v[x])return -1; ans+=v[x]; } return ans; } int main(){ scanf("%d",&Case); while(Case--){ scanf("%d%d",&n,&m); for(tot=i=1;i<=n;i++)scanf("%s",a[i]+1); while(m--){ scanf("%s",s+1); len=strlen(s+1); for(i=x=1;i<=len;i++){ if(!son[x][w=s[i]-'a'])son[x][w]=++tot; x=son[x][w]; } scanf("%d",&v[x]); } printf("%lld\n",solve()); for(i=0;i<=tot;i++)for(v[i]=j=0;j<26;j++)son[i][j]=0; tot=0; } }
D. Dividing the Points
#include<cstdio> #include<algorithm> #include<vector> using namespace std; typedef long long ll; const int N=1510; int Case,n,m,cq,i,j,k,x,y,z,dx,dy,q[N],at[N],col[N],old[N],d[N],cut,sa,ca,all,flag; vector<int>g[N]; ll U,D,K; struct P{ int x,y,p; P(){} P(int _x,int _y,int _p){x=_x,y=_y,p=_p;} }a[N],b[N]; inline bool cmp(const P&a,const P&b){ if(a.x!=b.x)return a.x<b.x; return a.y<b.y; } inline bool cmp2(const P&a,const P&b){return a.x*b.y>a.y*b.x;} inline void flip(int x){ if(col[x]==0)sa-=d[x],ca--;else sa+=d[x],ca++; for(int k=0;k<g[x].size();k++)if(col[x]!=col[g[x][k]>>7])cut-=g[x][k]&127;else cut+=g[x][k]&127; col[x]^=1; } inline void up(){ if(!ca||ca==n)return; if(!flag){U=cut,D=1LL*sa*(all-sa),flag=1;return;} if(U*sa*(all-sa)>cut*D)U=cut,D=1LL*sa*(all-sa); } ll gcd(ll a,ll b){return b?gcd(b,a%b):a;} int main(){ scanf("%d",&Case); while(Case--){ scanf("%d%d",&n,&m); for(i=1;i<=n;i++)scanf("%d%d",&a[i].x,&a[i].y),a[i].p=i; sort(a+1,a+n+1,cmp); for(i=1;i<=n;i++)at[a[i].p]=i; all=flag=0; for(i=1;i<=n;i++)g[i].clear(),d[i]=0; while(m--){ scanf("%d%d%d",&x,&y,&z); x=at[x],y=at[y]; g[x].push_back(y<<7|z); g[y].push_back(x<<7|z); d[x]+=z,d[y]+=z,all+=z*2; } for(i=1;i<=n;i++){ m=0; for(j=1;j<=n;j++)if(i!=j){ dx=a[j].x-a[i].x,dy=a[j].y-a[i].y; if(dx<0||dx==0&&dy>0)dx=-dx,dy=-dy,col[j]=0;else col[j]=1; b[++m]=P(dx,dy,j); }else col[j]=1; sort(b+1,b+m+1,cmp2); cut=sa=ca=0; for(j=1;j<=n;j++)if(col[j]==0){ sa+=d[j],ca++; for(k=0;k<g[j].size();k++)if(col[g[j][k]>>7]==1)cut+=g[j][k]&127; } for(j=1;j<=m;j=k){ for(k=j;k<=m&&b[j].x*b[k].y==b[j].y*b[k].x;k++); for(q[cq=1]=i,x=j;x<k;x++)q[++cq]=b[x].p; sort(q+1,q+cq+1); for(x=1;x<=cq;x++)if(col[q[x]])flip(q[x]),old[x]=0;else old[x]=1; for(x=1;x<=cq;x++)flip(q[x]),up(); for(x=1;x<=cq;x++)flip(q[x]),up(); for(x=1;x<=cq;x++)if(old[x])flip(q[x]); } } U*=all; K=gcd(U,D); printf("%lld/%lld\n",U/K,D/K); } }
E. Easy DP Problem
#include<cstdio> typedef long long ll; const int N=100010,M=2500010,K=1000000; int Case,n,m,i,x,tot,T[N],l[M],r[M],v[M];ll s[M],sum[N]; int ins(int x,int a,int b,int c){ int y=++tot; v[y]=v[x]+1; s[y]=s[x]+c; if(a==b)return y; int mid=(a+b)>>1; if(c<=mid)l[y]=ins(l[x],a,mid,c),r[y]=r[x]; else l[y]=l[x],r[y]=ins(r[x],mid+1,b,c); return y; } inline ll ask(int x,int y,int k){ int a=1,b=K,mid,tmp;ll ret=0; while(a<b){ mid=(a+b)>>1; tmp=v[r[x]]-v[r[y]]; if(k<=tmp){ a=mid+1; x=r[x]; y=r[y]; }else{ ret+=s[r[x]]-s[r[y]]; k-=tmp; b=mid; x=l[x]; y=l[y]; } } return ret+1LL*a*k; } int main(){ for(i=1;i<N;i++)sum[i]=sum[i-1]+1LL*i*i; scanf("%d",&Case); while(Case--){ scanf("%d",&n); for(i=1;i<=n;i++)scanf("%d",&x),T[i]=ins(T[i-1],1,K,x); scanf("%d",&m); while(m--){ int l,r,k; scanf("%d%d%d",&l,&r,&k); printf("%lld\n",ask(T[r],T[l-1],k)+sum[r-l+1]); } for(i=0;i<=tot;i++)l[i]=r[i]=v[i]=s[i]=0; tot=0; } }
G. Gliding
#include<cstdio> #include<cmath> #include<algorithm> using namespace std; typedef double db; const int N=4005; const db inf=1e100; int Case,n,sx,sy,tx,ty,vf,vp,vh,i,j,x,y;db A,B,tmp,ans,f[N]; struct E{int x,y,v,p;}e[N]; inline bool cmp(const E&a,const E&b){return a.v<b.v;} int main(){ scanf("%d",&Case); while(Case--){ scanf("%d%d%d%d%d%d%d%d",&sx,&sy,&tx,&ty,&vf,&vp,&vh,&n); for(i=0;i<=n;i++)scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].v),e[i].p=i; sort(e,e+n+1,cmp); for(i=0;i<=n;i++)f[i]=e[i].p?inf:0; ans=inf; for(i=0;i<=n;i++)if(f[i]<1e50&&e[i].v>vp){ A=f[i],B=((db)e[i].v)/((db)(e[i].v-vp)); x=e[i].x,y=e[i].y; tmp=A+sqrt((x-tx)*(x-tx)+(y-ty)*(y-ty))*B; if(tmp<ans)ans=tmp; for(j=i+1;j<=n;j++){ tmp=A+sqrt((x-e[j].x)*(x-e[j].x)+(y-e[j].y)*(y-e[j].y))*B; if(tmp<f[j])f[j]=tmp; } } printf("%.15f\n",(double)(ans/vh)); } }
H. Huge Clouds
#include<cstdio> #include<algorithm> using namespace std; typedef long double ld; const int N=505; int Case,n,m,ce,i,j,ban,cnt[N];ld ans; struct P{ int x,y; P(){} P(int _x,int _y){x=_x,y=_y;} P operator-(const P&v)const{return P(x-v.x,y-v.y);} int operator*(const P&v)const{return x*v.x+y*v.y;} void read(){scanf("%d%d",&x,&y);} }a[N],st[N],en[N],L(0,0),R(1,0); struct E{ ld x;int t; E(){} E(ld _x,int _t){x=_x,t=_t;} }e[N*N*2]; inline bool cmp(const E&a,const E&b){return a.x<b.x;} inline int cross(const P&a,const P&b){return a.x*b.y-a.y*b.x;} inline bool point_on_segment(const P&p,const P&a,const P&b){ return cross(b-a,p-a)==0&&(p-a)*(p-b)<=0; } inline ld line_intersection(const P&a,const P&b,const P&p,const P&q){ int U=cross(p-a,q-p),D=cross(b-a,q-p); if(!D)return -1; return ((ld)U)/((ld)D); } inline void ins(int x){ if(!cnt[x])ban++; cnt[x]++; } inline void del(int x){ cnt[x]--; if(!cnt[x])ban--; } inline ld solve(){ ce=ban=0;ans=0; for(i=1;i<=n;i++)cnt[i]=0; for(i=1;i<=n;i++){ for(j=1;j<=m;j++)if(point_on_segment(a[i],st[j],en[j]))break; if(j<=m){ ins(i); continue; } for(j=1;j<=m;j++){ if(cross(en[j]-st[j],a[i]-st[j])==0)continue; ld A=line_intersection(a[i],st[j],L,R),B=line_intersection(a[i],en[j],L,R); if(A<0&&B<0)continue; if(A>0&&B>0){ A=line_intersection(L,R,a[i],st[j]),B=line_intersection(L,R,a[i],en[j]); if(A>B)swap(A,B); e[++ce]=E(A,i); e[++ce]=E(B,-i); continue; } P C,D; if(A>0)C=st[j],D=en[j];else C=en[j],D=st[j]; ld F=line_intersection(L,R,a[i],C); if(cross(D-a[i],C-a[i])<0){ e[++ce]=E(F,i); }else{ ins(i); e[++ce]=E(F,-i); } } } if(ban==n)return -1; sort(e+1,e+ce+1,cmp); for(i=1;i<=ce;i++){ if(ban==n)ans+=e[i].x-e[i-1].x; if(e[i].t>0)ins(e[i].t);else del(-e[i].t); } if(ban==n)return -1; return ans; } int main(){ scanf("%d",&Case); while(Case--){ scanf("%d%d",&n,&m); for(i=1;i<=n;i++)a[i].read(); for(i=1;i<=m;i++)st[i].read(),en[i].read(); printf("%.15f\n",(double)solve()); } }
I. Invoking the Magic
#include<cstdio> #include<algorithm> using namespace std; const int N=200010; int Case,n,m,i,x,y,a[N],b[N],c[N],f[N],size[N],ans; int F(int x){return f[x]==x?x:f[x]=F(f[x]);} int main(){ scanf("%d",&Case); while(Case--){ scanf("%d",&n); m=0; for(i=1;i<=n;i++)scanf("%d%d",&a[i],&b[i]),c[++m]=a[i],c[++m]=b[i]; sort(c+1,c+m+1); for(i=1;i<=m;i++)f[i]=i,size[i]=0; for(i=1;i<=n;i++){ x=lower_bound(c+1,c+m+1,a[i])-c; y=lower_bound(c+1,c+m+1,b[i])-c; if(F(x)!=F(y))f[f[x]]=f[y]; } for(i=1;i<=m;i++)size[F(i)]++; for(ans=i=1;i<=m;i++)ans=max(ans,size[i]); printf("%d\n",ans); } }
J. Just an Old Problem
#include<cstdio> #include<map> using namespace std; typedef unsigned int U; const int N=50010,M=100010,K=7,MX=881; const U inf=~0U; int Case,n,m,i,j,k,S,x,y,z,g[N],v[M<<1],w[M<<1],nxt[M<<1],ed,dep[N]; int cnt[K+2],pool[K+1][MX],merge[K+1][MX][K],push[K+1][MX],pop[K+1][MX]; map<int,int>id[K+1]; struct Info{ U x,y; Info(){} Info(U _x,U _y){x=_x,y=_y;} void up(const Info&b,U z=0){ if(x<b.x+z)return; if(x>b.x+z){ x=b.x+z; y=b.y; return; } y+=b.y; } }f[2][MX]; int o; inline int bit(int S,int x){return S>>(x*3)&7;} inline bool check(int S,int x){ for(int i=0;i<x;i++)if(bit(S,i)==bit(S,x))return 1; return 0; } inline int unite(int S,int x,int y){ int T=S,A=bit(S,x),B=bit(S,y); if(A==B)return -1; for(int i=0;i<=x;i++)if(bit(S,i)==A)T^=(A^B)<<(i*3); return T; } inline int get(int S){ int i,x,m=0,T=0; static int vis[K+1]; for(i=1;i<=K;i++)vis[i]=0; for(i=0;i<K;i++){ x=bit(S,i); if(x){ if(!vis[x])vis[x]=++m; T|=vis[x]<<(i*3); } } return T; } void go(int x,int S,int y){ if(x){ cnt[x]++; pool[x][cnt[x]]=S; id[x][S]=cnt[x]; } if(x==K)return; for(int i=1;i<=y;i++)go(x+1,S|(i<<(x*3)),i==y?y+1:y); } inline void add(int x,int y,int z){v[++ed]=y;w[ed]=z;nxt[ed]=g[x];g[x]=ed;} void dfs(int x,int d){ int A=cnt[d],B=cnt[d+1]; dep[x]=d; for(int i=g[x];i;i=nxt[i]){ int u=dep[v[i]]; if(!u)continue; for(int j=1;j<=A;j++)if(f[o][j].x<inf)f[o][merge[d][j][u]].up(f[o][j],w[i]); } for(int i=g[x];i;i=nxt[i]){ int u=v[i]; if(dep[u])continue; for(int j=1;j<=B;j++)f[o^1][j].x=inf; for(int j=1;j<=A;j++)f[o^1][push[d][j]].up(f[o][j]); o^=1; dfs(u,d+1); for(int j=1;j<=A;j++)f[o^1][j].x=inf; for(int j=1;j<=B;j++)f[o^1][pop[d+1][j]].up(f[o][j]); o^=1; } } int main(){ go(0,0,1); for(i=1;i<=K;i++)for(j=1;j<=cnt[i];j++){ S=pool[i][j]; if(i<K)push[i][j]=id[i+1][get(S|(7<<(i*3)))]; if(i>1&&check(S,i-1))pop[i][j]=id[i-1][S^(bit(S,i-1)<<((i-1)*3))]; for(k=1;k<i;k++){ x=unite(S,i-1,k-1); if(~x)merge[i][j][k]=id[i][get(x)]; } } scanf("%d",&Case); while(Case--){ scanf("%d%d",&n,&m); for(ed=0,i=1;i<=n;i++)g[i]=dep[i]=0; while(m--)scanf("%d%d%d",&x,&y,&z),add(x,y,z),add(y,x,z); o=0; f[0][1]=Info(0,1); dfs(1,1); U ans=f[o][1].x*f[o][1].y; printf("%u\n",ans&((1<<30)-1));//mod 2^30 } }
K. Killing the Brute-force
#include<cstdio> const int N=55; int Case,n,m,i,a[N],b[N]; int main(){ scanf("%d",&Case); while(Case--){ scanf("%d",&m); for(i=1;i<=m;i++)scanf("%d",&a[i]); for(i=1;i<=m;i++)scanf("%d",&b[i]); n=-1; for(i=1;i<=m;i++)if(a[i]*3<b[i]){ n=i; break; } printf("%d\n",n); } }
L. List of Products
#include<cstdio> #include<algorithm> using namespace std; typedef unsigned int U; typedef long long ll; typedef unsigned long long ull; const int N=100010,MX=1000010; int Case,n,m,tot,i,j,k,x,f[MX],p[MX],pool[N*3][19],a[N],b[N],l,r,mid; ll K; int st[N],en[N]; inline void fac(int x,int o){ int A=0,B,cnt=0; while(x>1){ int y=f[x]; if(y>A){ if(A)pool[o][++cnt]=A<<6|B; A=y; B=0; } B++; x/=y; } if(A)pool[o][++cnt]=A<<6|B; pool[o][0]=cnt; } inline int compare(int A,int B){ int n=pool[A][0],m=pool[B][0],i=1; while(i<=n&&i<=m){ if(pool[A][i]==pool[B][i]){ i++; continue; } if((pool[A][i]>>6)!=(pool[B][i]>>6))return pool[A][i]>pool[B][i]?-1:1; return pool[A][i]<pool[B][i]?-1:1; } if(n==m)return 0; return n<m?-1:1; } inline void merge(int A,int B,int C){ int n=pool[A][0],m=pool[B][0],i=1,j=1,k=0; while(i<=n&&j<=m){ if((pool[A][i]>>6)==(pool[B][j]>>6)){ pool[C][++k]=pool[A][i++]+(pool[B][j++]&63); continue; } pool[C][++k]=pool[A][i]<pool[B][j]?pool[A][i++]:pool[B][j++]; } while(i<=n)pool[C][++k]=pool[A][i++]; while(j<=m)pool[C][++k]=pool[B][j++]; pool[C][0]=k; } inline ll cal(int o){ int n=pool[o][0];ll ret=1; for(int i=1;i<=n;i++){ int A=pool[o][i]>>6,B=pool[o][i]&63; while(B--)ret*=A; } return ret; } inline bool cmp(int x,int y){return compare(x,y)<0;} U SX=335634763,SY=873658265,SZ=192849106,SW=746126501; inline ull xorshift128(){ U t=SX^(SX<<11); SX=SY; SY=SZ; SZ=SW; return SW=SW^(SW>>19)^t^(t>>8); } inline ull myrand(){return (xorshift128()<<32)^xorshift128();} int main(){ for(i=2;i<MX;i++){ if(!f[i])f[i]=i,p[tot++]=i; for(j=0;j<tot&&i*p[j]<MX;j++){ f[i*p[j]]=p[j]; if(i%p[j]==0)break; } } scanf("%d",&Case); while(Case--){ scanf("%d%d%lld",&n,&m,&K); tot=0; for(i=1;i<=n;i++){ scanf("%d",&x); fac(x,a[i]=++tot); } for(i=1;i<=m;i++){ scanf("%d",&x); fac(x,b[i]=++tot); } sort(a+1,a+n+1,cmp); sort(b+1,b+m+1,cmp); //find smallest that >= k pool[l=++tot][0]=0; merge(a[n],b[m],r=++tot); while(1){ ll have=0; for(i=1,j=k=m;i<=n;i++){ while(j){ merge(a[i],b[j],tot+1); if(compare(tot+1,r)>=0)j--;//<r else break; } while(k){ merge(a[i],b[k],tot+1); if(compare(tot+1,l)>0)k--;//>l else break; } //[k+1..j] st[i]=k+1,en[i]=j; if(k+1<=j)have+=j-k; } if(!have)break; have=myrand()%have+1; for(i=1;i<=n;i++)if(st[i]<=en[i]){ if(have>en[i]-st[i]+1)have-=en[i]-st[i]+1; else{ merge(a[i],b[st[i]+have-1],mid=++tot); break; } } have=0; for(i=1,j=m;i<=n;i++){ while(j){ merge(a[i],b[j],tot+1); if(compare(tot+1,mid)>0)j--;//<=mid else break; } have+=j; } if(have>=K)r=mid;else l=mid; } printf("%lld\n",cal(r)); } }