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

浙公网安备 33010602011771号