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));
  }
}

  

posted @ 2022-01-14 21:31  Claris  阅读(180)  评论(0编辑  收藏  举报