2024“钉耙编程”中国大学生算法设计超级联赛(4)
题面:
https://files.cnblogs.com/files/clrs97/%E7%AC%AC%E5%9B%9B%E5%9C%BA%E9%A2%98%E9%9D%A2.pdf
题解:
https://files.cnblogs.com/files/clrs97/%E7%AC%AC%E5%9B%9B%E5%9C%BA%E9%A2%98%E8%A7%A3.pdf
Code:
A. 超维攻坚
#include<cstdio> const int N=15,inf=~0U>>1; int Case,n,i,j,k,S,o;bool ok[(1<<N)+1]; struct P{ int x,y,z; P(){} P(int _x,int _y,int _z){x=_x,y=_y,z=_z;} P operator-(const P&p)const{return P(x-p.x,y-p.y,z-p.z);} P operator*(const P&p)const{return P(y*p.z-z*p.y,z*p.x-x*p.z,x*p.y-y*p.x);} int operator^(const P&p)const{return x*p.x+y*p.y+z*p.z;} }p[N]; inline int ptoplane(const P&a,const P&b,const P&c,const P&p){return((b-a)*(c-a))^(p-a);} inline void umin(int&a,int b){a>b?(a=b):0;} inline void umax(int&a,int b){a<b?(a=b):0;} inline bool colinear(const P&a,const P&b,const P&p){ P t=(a-b)*(b-p); return !t.x&&!t.y&&!t.z; } inline int sgn(int x){ if(x>0)return 1; if(x<0)return -1; return 0; } //12v^4 inline bool check(const P&a,const P&b,const P&c,const P&p){ return (((b-a)*(c-a))^((b-a)*(p-a)))>=0; } struct Face{ P a,b,c; int sgn; bool inside(const P&p)const{ return check(a,b,c,p)&&check(b,c,a,p)&&check(c,a,b,p); } }f[N*N*N]; int main(){ scanf("%d",&Case); while(Case--){ scanf("%d",&n); for(i=0;i<n;i++)scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].z); for(i=1;i<1<<n;i++)ok[i]=0; for(S=1;S<1<<n;S++){ if(__builtin_popcount(S)<=1){ ok[S]=1; continue; } int m=0; bool same=1; for(i=0;i<n;i++)if(S>>i&1)for(j=0;j<i;j++)if(S>>j&1)for(k=0;k<j;k++)if(S>>k&1){ if(colinear(p[i],p[j],p[k]))continue; int l=inf,r=-inf; for(o=0;o<n;o++)if(S>>o&1){ int tmp=ptoplane(p[i],p[j],p[k],p[o]); umin(l,tmp); umax(r,tmp); } if(l<0&&r>0)continue; if(l||r)same=0; f[m].a=p[i]; f[m].b=p[j]; f[m].c=p[k]; f[m].sgn=sgn(l)+sgn(r); m++; } int mask=S; if(!m){ //colinear int xl=inf,xr=-inf; int yl=inf,yr=-inf; int zl=inf,zr=-inf; int idl=n,idr=0; for(i=0;i<n;i++)if(S>>i&1){ umin(xl,p[i].x);umax(xr,p[i].x); umin(yl,p[i].y);umax(yr,p[i].y); umin(zl,p[i].z);umax(zr,p[i].z); umin(idl,i);umax(idr,i); } for(i=0;i<n;i++){ if(S>>i&1)continue; if(!colinear(p[idl],p[idr],p[i]))continue; if(p[i].x<xl||p[i].x>xr)continue; if(p[i].y<yl||p[i].y>yr)continue; if(p[i].z<zl||p[i].z>zr)continue; mask|=1<<i; } }else if(same){ //just a face for(i=0;i<n;i++){ if(S>>i&1)continue; if(ptoplane(f[0].a,f[0].b,f[0].c,p[i]))continue; for(j=0;j<m;j++)if(f[j].inside(p[i])){ mask|=1<<i; break; } } }else{ for(i=0;i<n;i++){ if(S>>i&1)continue; for(j=0;j<m;j++){ int tmp=sgn(ptoplane(f[j].a,f[j].b,f[j].c,p[i])); if(tmp&&tmp!=f[j].sgn)break; } if(j==m)mask|=1<<i; } } ok[mask]=1; } int ans=0; for(i=1;i<1<<n;i++)if(ok[i])ans++; printf("%d\n",ans); } }
B. 黑白边游戏
#include<cstdio> #include<cstdlib> #include<algorithm> #include<map> #include<vector> using namespace std; typedef unsigned int U; typedef pair<U,U>P; const int N=9,K=6,M=13055,CNT=305,inf=~0U>>1; int a[CNT],b[CNT],f[CNT][M],perm[N],deg[N],d[N][N];bool g[N][N];U minS; U two[N],w[N];P ident[N]; inline void umin(int&a,int b){a>b?(a=b):0;} inline void umax(int&a,int b){a<b?(a=b):0;} struct Info{ int n,m,tot,id[N][N],apsp[K][K][M]; map<U,int>T; U mask[M]; vector<int>adj[M]; void init(int _n){ int i,j,k,o,A,B; n=_n; for(i=0;i<n;i++)for(j=0;j<i;j++)id[i][j]=id[j][i]=m++; dfs(0); for(i=1;i<=tot;i++){ sort(adj[i].begin(),adj[i].end()); adj[i].erase(unique(adj[i].begin(),adj[i].end()),adj[i].end()); } int d[N][N]; for(A=1;A<K;A++)for(B=1;B<K;B++)for(o=1;o<=tot;o++){ U S=mask[o]; for(i=0;i<n;i++)for(j=0;j<i;j++)d[i][j]=d[j][i]=(S>>id[i][j]&1)?B:A; for(i=0;i<n;i++)d[i][i]=0; for(k=0;k<n;k++)for(i=0;i<n;i++)for(j=0;j<n;j++)umin(d[i][j],d[i][k]+d[k][j]); int sum=0; for(i=0;i<n;i++)for(j=0;j<n;j++)sum+=d[i][j]; apsp[A][B][o]=sum; } } void reorder(int x,int vis){ if(x==n){ U now=0; for(int i=0;i<n;i++)for(int j=0;j<i;j++)if(g[perm[i]][perm[j]])now|=1U<<id[i][j]; if(minS>now)minS=now; return; } P mindeg(~0U>>1,0); for(int i=0;i<n;i++)if(!(vis>>i&1)&&mindeg>ident[i])mindeg=ident[i]; for(int i=0;i<n;i++)if(!(vis>>i&1)&&mindeg==ident[i]){ perm[x]=i; reorder(x+1,vis|(1<<i)); } } U adjust(U S){ int i,j; for(i=0;i<n;i++)deg[i]=0; for(i=0;i<n;i++)for(j=0;j<i;j++){ g[i][j]=g[j][i]=S>>id[i][j]&1; if(g[i][j])deg[i]++,deg[j]++; } for(i=0;i<n;i++){ two[i]=0; for(j=0;j<n;j++)if(g[i][j])two[i]+=w[deg[j]]; } for(i=0;i<n;i++)ident[i]=P(deg[i],two[i]); minS=~0U; int vis=0,cnt=0; for(i=0;i<n;i++)if(deg[i]==0){ vis|=1<<i; perm[cnt++]=i; } for(i=0;i<n;i++)if(deg[i]==n-1){ vis|=1<<i; perm[cnt++]=i; } reorder(cnt,vis); return minS; } int dfs(U S){ S=adjust(S); int&x=T[S]; if(x)return x; x=++tot; mask[tot]=S; for(int i=0;i<m;i++)if(!(S>>i&1)){ int y=dfs(S^(1U<<i)); adj[x].emplace_back(y); adj[y].emplace_back(x); } return x; } void solve(int cnt){ for(int j=1;j<=tot;j++)f[cnt+1][j]=0; for(int i=cnt;i;i--){ int A=a[i],B=b[i]; for(int j=1;j<=tot;j++){ int cur=-inf; for(const auto&k:adj[j])umax(cur,apsp[A][B][k]-f[i+1][k]); f[i][j]=cur; } } printf("%d\n",f[1][1]); } }info[N]; int main(){ for(int i=0;i<N;i++)w[i]=(rand()<<15)^rand(); for(int i=2;i<=8;i++)info[i].init(i); int Case; scanf("%d",&Case); while(Case--){ int n,cnt; scanf("%d%d",&n,&cnt); for(int i=1;i<=cnt;i++)scanf("%d%d",&a[i],&b[i]); info[n].solve(cnt); } }
C. 最优 K 子段
#include<iostream> #include<algorithm> #include<set> using namespace std; typedef pair<int,int>P; const int N=200005; int Case,n,k,i,j,a[N];bool vis[N],is_prime[N],OK; int L,R,MID,ANS; set<P>T; inline void ins(int sum,int ptr){ T.insert(P(sum,ptr)); } inline bool valid(int sum,int ptr){ for(set<P>::iterator it=T.begin();it!=T.end();it++){ if(sum-it->first<MID)return 0; if(is_prime[ptr-it->second])return 1; } return 0; } inline bool check(){ for(int cur=1,ptr=1;cur<=k;cur++){ if(ptr>n)return 0; T.clear(); ins(0,ptr-1); for(int sum=0;;ptr++){ if(ptr>n)return 0; sum+=a[ptr]; if(valid(sum,ptr)){ ptr++; break; } ins(sum,ptr); } } return 1; } int main(){ for(i=2;i<N;i++)if(!vis[i]){ is_prime[i]=1; for(j=i;j<N;j+=i)vis[j]=1; } ios_base::sync_with_stdio(0);cin.tie(0); cin>>Case; while(Case--){ cin>>n>>k; L=R=OK=0; for(i=1;i<=n;i++){ cin>>a[i]; if(a[i]>0)R+=a[i];else L+=a[i]; } while(L<=R){ MID=(L+R)/2; if(check()){ OK=1; ANS=MID; L=MID+1; }else R=MID-1; } if(OK)cout<<ANS<<"\n";else cout<<"impossible\n"; } }
D. 分组
#include<cstdio> #include<algorithm> using namespace std; const int N=21,M=10,LEN=(1<<M)+5; int Case,n,m,i,ans,val[N],w[LEN],q[LEN],at[LEN]; bool fl[N][LEN],fr[N][LEN]; inline bool cmp(int x,int y){return w[x]<w[y];} inline void umin(int&a,int b){a>b?(a=b):0;} inline void umax(int&a,int b){a<b?(a=b):0;} void dfs(int x,int suml,int sumr){ if(x==n){ for(int i=0,ml=-1,mr=-1;i<1<<m;i++){ int o=q[i]; if(fl[n][o]&&w[o]>=w[o^suml]){ umax(ml,w[o^suml]); if(~mr)umin(ans,w[o]-min(w[o^suml],mr)); } if(fr[n][o]&&w[o]>=w[o^sumr]){ umax(mr,w[o^sumr]); if(~ml)umin(ans,w[o]-min(w[o^sumr],ml)); } } return; } int v=val[x]; for(int i=0;i<1<<m;i++){ fl[x+1][i]=fl[x][i]|fl[x][i^v]; fr[x+1][i]=fr[x][i]; } dfs(x+1,suml^v,sumr); for(int i=0;i<1<<m;i++){ fl[x+1][i]=fl[x][i]; fr[x+1][i]=fr[x][i]|fr[x][i^v]; } dfs(x+1,suml,sumr^v); } int main(){ scanf("%d",&Case); while(Case--){ scanf("%d%d",&n,&m); for(i=0;i<n;i++)scanf("%d",&val[i]); for(i=0;i<1<<m;i++)scanf("%d",&w[i]),q[i]=i; sort(q,q+(1<<m),cmp); for(i=0;i<1<<m;i++)at[q[i]]=i; for(i=0;i<1<<m;i++)fl[1][i]=fr[1][i]=0; fl[1][0]=fr[1][0]=1; fl[1][val[0]]=1; ans=~0U>>1; dfs(1,val[0],0); printf("%d\n",ans); } }
E. 多层血条
#include<cstdio> const int N=805; int Case,n,m,hp,dmg,i,j;char f[N]; int main(){ scanf("%d",&Case); while(Case--){ scanf("%d%d%d%d",&n,&m,&hp,&dmg); for(i=0;i<m;i++)f[i]=' '; int top=(hp-1)/m; int lim=(hp-1)%m; int col=top%5+'A'; int nxt=(top+4)%5+'A'; if(top)for(i=0;i<m;i++)f[i]=nxt; for(i=0;i<=lim;i++)f[i]=col; if(dmg>m)dmg=m; while(dmg--){ f[lim]='.'; lim=(lim+m-1)%m; } putchar('+'); for(i=0;i<m;i++)putchar('-'); puts("+"); for(i=0;i<n;i++){ putchar('|'); for(j=0;j<m;j++)putchar(f[j]); puts("|"); } putchar('+'); for(i=0;i<m;i++)putchar('-'); puts("+"); } }
F. 延时操控
#include<cstdio> const int N=55,K=5,P=1000000007; const int dx[4]={-1,1,0,0},dy[4]={0,0,-1,1}; int Case,n,m,delay,hp,px,py,ex,ey,i,j,k,x,y,d,lim,o; int f[2][N][N][K][K*2][K*2],g[2][N][N],ans; bool ban[N][N]; char ch[N]; inline void up(int&a,int b){a=a+b<P?a+b:a+b-P;} inline bool check(int x,int y){ if(x<1||x>n||y<1||y>n)return 0; return !ban[x][y]; } int main(){ scanf("%d",&Case); while(Case--){ scanf("%d%d%d%d",&n,&m,&delay,&hp); for(i=1;i<=n;i++){ scanf("%s",ch+1); for(j=1;j<=n;j++){ if(ch[j]=='#')ban[i][j]=1;else ban[i][j]=0; if(ch[j]=='P')px=i,py=j; if(ch[j]=='E')ex=i,ey=j; } } ex-=px,ey-=py; for(o=0;o<2;o++)for(i=1;i<=n;i++)for(j=1;j<=n;j++)for(k=0;k<hp;k++)for(x=-k;x<=k;x++){ lim=k-(x>0?x:-x); for(y=-lim;y<=lim;y++)f[o][i][j][k][x+K][y+K]=0; } for(o=0;o<2;o++)for(i=1;i<=n;i++)for(j=1;j<=n;j++)g[o][i][j]=0; m-=delay; f[0][px][py][0][K][K]=1; o=0; while(m--){ for(i=1;i<=n;i++)for(j=1;j<=n;j++)for(k=0;k<hp;k++)for(x=-k;x<=k;x++){ lim=k-(x>0?x:-x); for(y=-lim;y<=lim;y++)f[o^1][i][j][k][x+K][y+K]=0; } for(i=1;i<=n;i++)for(j=1;j<=n;j++)for(k=0;k<hp;k++)for(x=-k;x<=k;x++){ lim=k-(x>0?x:-x); for(y=-lim;y<=lim;y++){ int now=f[o][i][j][k][x+K][y+K]; if(!now)continue; for(d=0;d<4;d++){ px=i+dx[d],py=j+dy[d]; if(!check(px,py))continue; if(check(px+ex+x,py+ey+y))up(f[o^1][px][py][k][x+K][y+K],now); else if(k+1==hp)up(g[0][px][py],now); else up(f[o^1][px][py][k+1][x-dx[d]+K][y-dy[d]+K],now); } } } o^=1; } o=0; while(delay--){ for(i=1;i<=n;i++)for(j=1;j<=n;j++)g[o^1][i][j]=0; for(i=1;i<=n;i++)for(j=1;j<=n;j++){ int now=g[o][i][j]; if(!now)continue; for(d=0;d<4;d++){ px=i+dx[d],py=j+dy[d]; if(!check(px,py))continue; up(g[o^1][px][py],now); } } o^=1; } ans=0; for(i=1;i<=n;i++)for(j=1;j<=n;j++)up(ans,g[o][i][j]); printf("%d\n",ans); } }
G. 序列更新
#include<iostream> #include<algorithm> #include<cmath> using namespace std; const int N=250005; int Case,n,q,lim,i,k,x,a[N],b[N],c[N],cs,ct,S[N],T[N]; long long sum; inline void fix(int&x){ while(x<0)x+=n; while(x>=n)x-=n; } inline void gao(int x,int y){ fix(x); fix(y); if(a[x]>=b[y])return; sum+=b[y]-a[x]; a[x]=b[y]; } int main(){ ios_base::sync_with_stdio(0);cin.tie(0); cin>>Case; while(Case--){ cin>>n>>q; sum=0; for(i=0;i<n;i++){ cin>>a[i]; sum+=a[i]; } for(i=0;i<n;i++)cin>>b[i]; for(i=0;i<n;i++)c[i]=b[i]; sort(c,c+n); lim=sqrt(n); lim=max(lim,1); lim=min(lim,n); lim=c[n-lim]; cs=ct=0; for(i=0;i<n;i++){ if(a[i]<=lim)S[cs++]=i; if(b[i]>lim)T[ct++]=i; } while(q--){ cin>>k; for(i=0;i<cs;){ x=S[i]; gao(x,x+k); if(a[x]>lim)swap(S[i],S[--cs]);else i++; } for(i=0;i<ct;i++){ x=T[i]; gao(x-k,x); } cout<<sum<<"\n"; } } }
H. 魔法卡牌
#include<cstdio> #include<algorithm> using namespace std; typedef unsigned long long ull; const int N=63,inf=~0U>>1; int Case,n,m,i,j,x,y,a[N],b[N],T[N],a_deg[N],b_deg[N]; ull a_all[N],a_ban[N],a_must[N],b_ban[N],nei[N],imp; bool a_imp[N],can[N][N][2][2]; struct P{ int val;ull way; P(){} P(int _val,ull _way){val=_val;way=_way;} void clr(){val=-inf;way=0;} void up(const P&b,int k=0){ if(val>b.val+k)return; if(val<b.val+k){ val=b.val+k; way=b.way; return; } way+=b.way; } void print(){printf("%d %llu\n",val,way);} }; P dfs(ull S){ if(!S)return P(0,1); int who=-1,best=inf; int cnt=__builtin_popcountll(S); if(imp&S)who=__builtin_ctzll(imp&S); else for(ull Q=S;Q;Q-=Q&-Q){ int x=__builtin_ctzll(Q); if(__builtin_popcountll(nei[x]&S)<=2)continue; int a_deg=__builtin_popcountll(a_all[x]&S); int b_deg=__builtin_popcountll(b_ban[x]&S); int now=T[cnt-a_deg-1]+T[cnt-b_deg-1]; if(now<best)who=x,best=now; } if(who<0){ P ans(0,1); for(ull Q=S;Q;){ int head=__builtin_ctzll(Q); Q-=Q&-Q; ull mask=S&nei[head]; if(!mask){ S^=1ULL<<head; ans.val+=max(a[head],b[head]); if(a[head]==b[head])ans.way*=2; continue; } if((mask&-mask)!=mask)continue; S^=1ULL<<head; static P dp[2][2]; int x=head,o=0; for(int i=0;i<2;i++)dp[0][i].clr(); dp[0][0]=P(a[x],1); dp[0][1]=P(b[x],1); while(S&nei[x]){ int y=__builtin_ctzll(S&nei[x]); S^=1ULL<<y; for(int j=0;j<2;j++)dp[o^1][j].clr(); for(int j=0;j<2;j++)if(dp[o][j].way){ if(can[x][y][j][0])dp[o^1][0].up(dp[o][j],a[y]); if(can[x][y][j][1])dp[o^1][1].up(dp[o][j],b[y]); } o^=1; x=y; } P cur(-inf,0); for(int j=0;j<2;j++)if(dp[o][j].way)cur.up(dp[o][j]); if(!cur.way)return P(-inf,0); ans.val+=cur.val; ans.way*=cur.way; Q&=S; } while(S){ int head=__builtin_ctzll(S); S^=1ULL<<head; static P dp[2][2][2]; int x=head,o=0; for(int i=0;i<2;i++)for(int j=0;j<2;j++)dp[0][i][j].clr(); dp[0][0][0]=P(a[x],1); dp[0][1][1]=P(b[x],1); while(S&nei[x]){ int y=__builtin_ctzll(S&nei[x]); S^=1ULL<<y; for(int i=0;i<2;i++){ for(int j=0;j<2;j++)dp[o^1][i][j].clr(); for(int j=0;j<2;j++)if(dp[o][i][j].way){ if(can[x][y][j][0])dp[o^1][i][0].up(dp[o][i][j],a[y]); if(can[x][y][j][1])dp[o^1][i][1].up(dp[o][i][j],b[y]); } } o^=1; x=y; } P cur(-inf,0); for(int i=0;i<2;i++)for(int j=0;j<2;j++) if(dp[o][i][j].way&&can[head][x][i][j])cur.up(dp[o][i][j]); if(!cur.way)return P(-inf,0); ans.val+=cur.val; ans.way*=cur.way; } return ans; } S^=1ULL<<who; P ans(-inf,0); for(int o=0;o<2;o++){ ull nS=S,SA=0,SB=0,Q=0; int val=0; if(!o){ if(a_imp[who])continue; val=a[who]; SA^=a_must[who]&nS; SB^=a_ban[who]&nS; Q=a_all[who]&S; }else{ val=b[who]; SB^=b_ban[who]&nS; Q=b_ban[who]&nS; } nS^=Q; while(Q){ int x=__builtin_ctzll(Q); if(SA>>x&1){ val+=a[x]; if(a_ban[x]&SA)break; if(a_must[x]&SB)break; if(a_imp[x])break; SA^=a_must[x]&nS; SB^=a_ban[x]&nS; Q^=a_all[x]&nS; nS^=a_all[x]&nS; }else{ val+=b[x]; if(b_ban[x]&SA)break; SB^=b_ban[x]&nS; Q^=b_ban[x]&nS; nS^=b_ban[x]&nS; } Q^=1ULL<<x; } if(Q)continue; P res=dfs(nS); ans.up(res,val); } return ans; } int main(){ for(i=0;i<N;i++){ if(i<=3)T[i]=1; else T[i]=max(T[i-1]+T[max(i-5,0)],max(T[i-2]+T[i-4],T[i-3]+T[i-3])); //printf("T[%d]=%d\n",i,T[i]); } scanf("%d",&Case); while(Case--){ scanf("%d%d",&n,&m); for(i=0;i<n;i++){ scanf("%d%d",&a[i],&b[i]); a_ban[i]=a_must[i]=b_ban[i]=0; } for(i=0;i<n;i++)for(j=0;j<n;j++)for(x=0;x<2;x++)for(y=0;y<2;y++)can[i][j][x][y]=1; while(m--){ char op[9]; scanf("%s%d%d",op,&x,&y); x--;y--; if(op[0]=='A'){ //x -> !y //y -> !x a_ban[x]|=1ULL<<y; a_ban[y]|=1ULL<<x; can[x][y][0][0]=0; can[y][x][0][0]=0; }else{ //x -> y //!y -> !x a_must[x]|=1ULL<<y; b_ban[y]|=1ULL<<x; can[x][y][0][1]=0; can[y][x][1][0]=0; } } imp=0; for(i=0;i<n;i++){ a_imp[i]=!!(a_ban[i]&a_must[i]); if(a_imp[i])imp|=1ULL<<i; a_all[i]=a_ban[i]|a_must[i]; nei[i]=a_all[i]|b_ban[i]; } P ans=dfs((1ULL<<n)-1); ans.print(); } }
I. 昵称检索
#include<iostream> #include<string> using namespace std; const int N=1000005,day[13]={0,31,29,31,30,31,30,31,31,30,31,30,31}; int Case,n,m,i,j,x,ans,suf[N],f[N][26],vis[26];string a; inline int godate(int*s){ int x=m+1; for(int i=3;~i;i--){ x--; if(x<1)return 0; x=f[x][s[i]]; } return x; } inline int goname(){ int x=0; for(int i=0;i<a.size();i++){ x++; if(x>m)return m+1; x=f[x][a[i]-'a']; } return x; } int main(){ ios_base::sync_with_stdio(0);cin.tie(0); cin>>Case; while(Case--){ cin>>n>>m>>a; for(j=0;j<10;j++)vis[j]=0; for(i=1;i<=m;i++){ if(a[i-1]>='0'&&a[i-1]<='9')vis[a[i-1]-'0']=i; for(j=0;j<10;j++)f[i][j]=vis[j]; } for(i=0;i<=m+1;i++)suf[i]=0; for(i=1;i<=12;i++)for(j=1;j<=day[i];j++){ static int pool[4]; pool[0]=i/10; pool[1]=i%10; pool[2]=j/10; pool[3]=j%10; x=godate(pool); if(x)suf[x]++; } for(i=m;i>1;i--)suf[i-1]+=suf[i]; for(j=0;j<26;j++)vis[j]=m+1; for(i=m;i;i--){ if(a[i-1]>='a'&&a[i-1]<='z')vis[a[i-1]-'a']=i; for(j=0;j<26;j++)f[i][j]=vis[j]; } ans=0; while(n--){ cin>>a; x=goname(); if(x<m)ans+=suf[x+1]; } cout<<ans<<"\n"; } }
J. 矩阵的周期
#include<cstdio> typedef unsigned long long ull; const int N=63,M=1200005; int Case,n,m,o,i,j,k,at[N],w[N],lim[N],nxt[M]; bool g[N][N],h[N][N],can[N][N]; ull adj[N],sub0[(1<<20)+1],sub1[(1<<20)+1],sub2[(1<<20)+1],f[M]; int gcd(int a,int b){return b?gcd(b,a%b):a;} inline int lcm(int a,int b){return a/gcd(a,b)*b;} inline int getlim(int o,int x){ if(!can[o][x])return 1; if(w[o]>1||w[x]>1||at[o]==at[x])return n; int ret=1; for(int i=0;i<n;i++)if(can[o][i]&&can[i][x])ret=lcm(ret,w[i]); return ret; } inline int getper(int x){ int m=lim[x],i,j; for(nxt[1]=j=0,i=2;i<=m;nxt[i++]=j){ while(j&&((f[j+1]^f[i])>>x&1))j=nxt[j]; if(!((f[j+1]^f[i])>>x&1))j++; } return m-nxt[m]; } int main(){ scanf("%d",&Case); while(Case--){ scanf("%d",&n); for(i=0;i<n;i++){ char ch[N]; scanf("%s",ch); adj[i]=0; for(j=0;j<n;j++){ g[i][j]=ch[j]=='1'; if(g[i][j])adj[i]|=1ULL<<j; } } for(i=0;i<n;i++)for(j=0;j<n;j++)can[i][j]=g[i][j]|(i==j); for(k=0;k<n;k++)for(i=0;i<n;i++)for(j=0;j<n;j++)can[i][j]|=can[i][k]&can[k][j]; for(i=0;i<n;i++)w[i]=0; for(i=0;i<n;i++){ if(w[i])continue; m=0; for(j=i;j<n;j++)if(can[i][j]&&can[j][i])m++; for(j=i;j<n;j++)if(can[i][j]&&can[j][i]){ at[j]=i; w[j]=m; } } for(o=0;o<N;o++){ for(i=0;i<n;i++)for(j=0;j<n;j++)h[i][j]=0; for(i=0;i<n;i++)for(j=0;j<n;j++)for(k=0;k<n;k++)h[i][k]|=g[i][j]&g[j][k]; for(i=0;i<n;i++)for(j=0;j<n;j++)g[i][j]=h[i][j]; } m=1<<(n<20?n:20); for(i=0;i<m;i++)sub0[i]=sub1[i]=sub2[i]=0; for(i=0;i<n;i++){ j=i; if(j<20){sub0[1<<j]|=adj[i];continue;}else j-=20; if(j<20){sub1[1<<j]|=adj[i];continue;}else j-=20; sub2[1<<j]|=adj[i]; } for(i=2;i<m;i++){ j=i&-i; sub0[i]=sub0[i^j]|sub0[j]; sub1[i]=sub1[i^j]|sub1[j]; sub2[i]=sub2[i^j]|sub2[j]; } for(o=0;o<n;o++){ m=1; for(i=0;i<n;i++){ lim[i]=getlim(o,i)*2; if(m<lim[i])m=lim[i]; } ull S=0; for(i=0;i<n;i++)if(g[o][i])S|=1ULL<<i; for(i=1;i<=m;i++){ f[i]=S; S=sub0[S&1048575]|sub1[S>>20&1048575]|sub2[S>>40]; } for(i=0;i<n;i++)printf("%d%c",getper(i),i+1<n?' ':'\n'); } } }
K. 找环
#include<iostream> using namespace std; typedef unsigned int U; typedef unsigned long long ull; const int N=1005,M=2005,TOT=N*M*11,BASE=998244353,P=1000000007; ull weight[N]; 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 Case,inv[N],n,m,i,j,res,f[N][N],tot,l[TOT],r[TOT],val[TOT];ull sum[TOT]; struct E{int x,y,z;}e[M]; struct Frac{ int u1,u2,d; Frac(){} Frac(int _u1,int _u2,int _d){u1=_u1,u2=_u2,d=_d;} }; int ins(int x,int a,int b,int c){ int y=++tot; val[y]=val[x]+1; sum[y]=sum[x]+weight[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 bool smaller(int x,int y){ if(y<0)return 1; if(sum[x]==sum[y])return 0; int a=1,b=n,mid; while(a<b){ mid=(a+b)>>1; if(sum[r[x]]==sum[r[y]]){ b=mid; x=l[x]; y=l[y]; }else{ a=mid+1; x=r[x]; y=r[y]; } } return val[x]<val[y]; } inline int compare(const Frac&A,const Frac&B){ if(A.u1<0&&B.u1<0)return 0; if(A.u1<0)return 1; if(B.u1<0)return -1; int a=1,b=n,mid; int A1=A.u1,A2=A.u2,B1=B.u1,B2=B.u2,AD=A.d,BD=B.d; if((sum[A1]-sum[A2])*BD==(sum[B1]-sum[B2])*AD)return 0; //(A1-A2)/AD<(B1-B2)/BD //(A1-A2)*BD<(B1-B2)*AD while(a<b){ mid=(a+b)>>1; if((sum[r[A1]]-sum[r[A2]])*BD==(sum[r[B1]]-sum[r[B2]])*AD){ b=mid; A1=l[A1]; A2=l[A2]; B1=l[B1]; B2=l[B2]; }else{ a=mid+1; A1=r[A1]; A2=r[A2]; B1=r[B1]; B2=r[B2]; } } int cross=(val[A1]-val[A2])*BD-(val[B1]-val[B2])*AD; if(!cross)return 0; return cross<0?-1:1; } void cal(int x,int y,int a,int b){ if(a==b){ res=(1LL*res*BASE+val[x]-val[y])%P; return; } int mid=(a+b)>>1; cal(r[x],r[y],mid+1,b); cal(l[x],l[y],a,mid); } int main(){ ios_base::sync_with_stdio(0);cin.tie(0); cin>>Case; for(inv[0]=inv[1]=1,i=2;i<N;i++)inv[i]=1LL*(P-P/i)*inv[P%i]%P; while(Case--){ cin>>n>>m; for(i=1;i<=m;i++)cin>>e[i].x>>e[i].y>>e[i].z; for(i=1;i<=n;i++)weight[i]=myrand(); for(i=0;i<=n+1;i++)for(j=1;j<=n;j++)f[i][j]=-1; for(j=1;j<=n;j++)f[0][j]=0; for(i=0;i<=n;i++)for(j=1;j<=m;j++){ int x=e[j].x,y=e[j].y,z=e[j].z; int root=f[i][x]; if(root<0)continue; int now=ins(root,1,n,z+1); if(smaller(now,f[i+1][y]))f[i+1][y]=now; } Frac ans=Frac(-1,-1,1); for(i=1;i<=n;i++){ int fin=f[n+1][i]; if(fin<0)continue; Frac me=Frac(0,0,1); for(j=0;j<=n;j++){ int now=f[j][i]; if(now<0)continue; Frac tmp(fin,now,n+1-j); if(compare(tmp,me)>0)me=tmp; } if(compare(me,ans)<0)ans=me; } if(ans.u1<0)cout<<"-1\n"; else{ res=0; cal(ans.u1,ans.u2,1,n); res=1LL*res*inv[ans.d]%P; cout<<res<<"\n"; } for(i=1;i<=tot;i++)l[i]=r[i]=val[i]=sum[i]=0; tot=0; } }
L. 寻找宝藏
#include<iostream> #include<algorithm> #include<vector> using namespace std; typedef long long ll; const int N=300005; int Case,n,m,i;ll bit[N];vector<int>gl[N],gr[N]; struct E{int y,w;ll pre,suf,val;}e[N]; struct Qry{int yl,yr;ll ans,ur,ru;}q[N]; inline void up(ll&a,ll b){a<b?(a=b):0;} inline void ins(int x,ll p){for(;x<=n;x+=x&-x)up(bit[x],p);} inline ll ask(int x){ ll t=0; for((x>n)&&(x=n);x;x-=x&-x)up(t,bit[x]); return t; } int main(){ ios_base::sync_with_stdio(0);cin.tie(0); cin>>Case; while(Case--){ cin>>n>>m; for(i=1;i<=n;i++){ cin>>e[i].y>>e[i].w; gl[i].clear(); gr[i].clear(); } for(i=1;i<=m;i++){ int xl,xr; cin>>xl>>q[i].yl>>xr>>q[i].yr; gl[xl].emplace_back(i); gr[xr].emplace_back(i); } for(i=1;i<=n;i++)bit[i]=0; for(i=1;i<=n;i++){ for(const auto&j:gl[i])q[j].ur=ask(q[j].yr); e[i].pre=ask(e[i].y)+e[i].w; ins(e[i].y,e[i].pre); for(const auto&j:gr[i])q[j].ru=ask(q[j].yl-1); } for(i=0;i<=n;i++)bit[i]=0; for(i=n;i;i--){ for(const auto&j:gr[i])q[j].ru+=ask(n+1-q[j].yl); e[i].suf=ask(n+1-e[i].y)+e[i].w; ins(n+1-e[i].y,e[i].suf); e[i].val=e[i].pre+e[i].suf-e[i].w; for(const auto&j:gl[i])q[j].ur+=ask(n+1-(q[j].yr+1)); } for(i=1;i<=m;i++)q[i].ans=max(q[i].ur,q[i].ru); for(i=1;i<=n;i++)bit[i]=0; for(i=1;i<=n;i++){ for(const auto&j:gl[i])up(q[j].ans,ask(n+1-(q[j].yr+1))); ins(n+1-e[i].y,e[i].val); } for(i=1;i<=n;i++)bit[i]=0; for(i=n;i;i--){ for(const auto&j:gr[i])up(q[j].ans,ask(q[j].yl-1)); ins(e[i].y,e[i].val); } for(i=1;i<=m;i++)cout<<q[i].ans<<"\n"; } }