模板
高精
#include<bits/stdc++.h> using namespace std; const int N=40005; struct bign{ int len,v[N];char s[N];int op; bign(){op=1;len=1;memset(v,0,sizeof(v));} void in(){ scanf("%s",s+1); int ls=strlen(s+1);len=ls; for(int i=1;i<=ls;i++) v[i]=s[ls-i+1]-'0'; } void out(){ bool ok=0; if(len==1&&v[1]==0)putchar('0'); for(int i=len;i>=1;i--) if(v[i]!=0||ok){printf("%d",v[i]);ok=1;}puts(""); } void del0(){while(v[len]==0&&len>1)len--;} friend bool operator < (bign &A,bign &B){ A.del0();B.del0(); if(A.len!=B.len)return A.len<B.len; for(int i=A.len;i>=1;i--) if(A.v[i]!=B.v[i])return A.v[i]<B.v[i]; return 0; } friend bign operator + (const bign &A,const bign &B){ int mx=max(A.len,B.len);bign C; C.len=mx; for(int i=1;i<=mx;i++)C.v[i]=A.v[i]+B.v[i]; for(int i=1;i<=mx;i++) if(C.v[i]>9)C.v[i]-=10,C.v[i+1]++; if(C.v[mx+1]>0)C.len=mx+1; return C; } friend bign operator * (const bign &A,const bign &B){ int mx=A.len+B.len+2;bign C; for(int i=1;i<=A.len;i++) for(int j=1;j<=B.len;j++) C.v[i+j-1]+=A.v[i]*B.v[j]; for(int i=1;i<=mx+2;i++) C.v[i+1]+=C.v[i]/10,C.v[i]%=10; while(C.v[mx]==0&&mx>1)mx--; C.len=mx; return C; } friend void Swap(bign &A,bign &B){bign C;C=A;A=B;B=C;} friend bign operator - (bign &A,bign &B){ bool ok=0; if(A<B)Swap(A,B),ok=1; bign C;int mx=A.len,flag=0; for(int i=1;i<=mx;i++){ C.v[i]=A.v[i]-B.v[i]-flag; if(C.v[i]<0)C.v[i]+=10,C.v[i+1]--,flag=1; else flag=0; } while(C.v[mx]==0&&mx>1)mx--; if(ok)Swap(A,B); C.len=mx;return C; } }a,b,c; int main(){ a.in();b.in(); c=a+b;c.out(); return 0; }
快读快写 (fread + fwrite A+B problem)
#include<bits/stdc++.h> using namespace std; char buf[1<<23],*p1=buf,*p2=buf,obuf[1<<23],*O=obuf; #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) inline int rd(){ 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<<3)+(x<<1)+(c^48),c=getchar(); return x*f; } void write(int x){ if(x>9)write(x/10); *O++=x%10+'0'; } int main(){ int a,b; a=rd();b=rd(); write(a+b);fwrite(obuf,O-obuf,1,stdout); return 0; }
火车头(卡常)
#pragma GCC optimize(3) #pragma GCC optimize("Ofast") #pragma GCC optimize("inline") #pragma GCC optimize("-fgcse") #pragma GCC optimize("-fgcse-lm") #pragma GCC optimize("-fipa-sra") #pragma GCC optimize("-ftree-pre") #pragma GCC optimize("-ftree-vrp") #pragma GCC optimize("-fpeephole2") #pragma GCC optimize("-ffast-math") #pragma GCC optimize("-fsched-spec") #pragma GCC optimize("unroll-loops") #pragma GCC optimize("-falign-jumps") #pragma GCC optimize("-falign-loops") #pragma GCC optimize("-falign-labels") #pragma GCC optimize("-fdevirtualize") #pragma GCC optimize("-fcaller-saves") #pragma GCC optimize("-fcrossjumping") #pragma GCC optimize("-fthread-jumps") #pragma GCC optimize("-funroll-loops") #pragma GCC optimize("-fwhole-program") #pragma GCC optimize("-freorder-blocks") #pragma GCC optimize("-fschedule-insns") #pragma GCC optimize("inline-functions") #pragma GCC optimize("-ftree-tail-merge") #pragma GCC optimize("-fschedule-insns2") #pragma GCC optimize("-fstrict-aliasing") #pragma GCC optimize("-fstrict-overflow") #pragma GCC optimize("-falign-functions") #pragma GCC optimize("-fcse-skip-blocks") #pragma GCC optimize("-fcse-follow-jumps") #pragma GCC optimize("-fsched-interblock") #pragma GCC optimize("-fpartial-inlining") #pragma GCC optimize("no-stack-protector") #pragma GCC optimize("-freorder-functions") #pragma GCC optimize("-findirect-inlining") #pragma GCC optimize("-fhoist-adjacent-loads") #pragma GCC optimize("-frerun-cse-after-loop") #pragma GCC optimize("inline-small-functions") #pragma GCC optimize("-finline-small-functions") #pragma GCC optimize("-ftree-switch-conversion") #pragma GCC optimize("-foptimize-sibling-calls") #pragma GCC optimize("-fexpensive-optimizations") #pragma GCC optimize("-funsafe-loop-optimizations") #pragma GCC optimize("inline-functions-called-once") #pragma GCC optimize("-fdelete-null-pointer-checks")
矩阵乘法 https://www.luogu.com.cn/problem/P1939
#include<bits/stdc++.h> #define int long long using namespace std; const int N=5,mod=1e9+7; struct mat{ int n,m,v[N][N]; mat(){memset(v,n=m=0,sizeof(v));} mat operator *(mat b){ mat c;c.n=n,c.m=b.m; for(int i=0;i<c.n;i++) for(int j=0;j<c.m;j++) for(int k=0;k<m;k++) c.v[i][j]=(1LL*c.v[i][j]+1LL*v[i][k]*b.v[k][j])%mod; return c; } }; mat power(mat a,int k){ mat ans=a; for(;k;k>>=1){ if(k&1)ans=ans*a; a=a*a; } return ans; } signed main(){ int T; scanf("%lld",&T); while(T--){ int k; scanf("%lld",&k); if(k<=3){cout<<1<<endl;continue;} k-=2; mat a; a.n=3;a.m=3; a.v[0][0]=1;a.v[0][1]=0;a.v[0][2]=1; a.v[1][0]=1;a.v[1][1]=0;a.v[1][2]=0; a.v[2][0]=0;a.v[2][1]=1;a.v[2][2]=0; mat ans=power(a,k); mat f; f.n=1;f.m=3; f.v[0][0]=1; f.v[1][0]=1; f.v[2][0]=1; f=f*ans; printf("%lld\n",f.v[0][0]); } return 0; }
左偏树 (小根堆) https://www.luogu.com.cn/problem/P3377
#include<bits/stdc++.h> using namespace std; const int N=2e5+10; int n,T; int rt[N],ls[N],rs[N],dis[N]; bool vis[N]; struct node{ int id,v; bool operator <(node& x)const{return v==x.v?id<x.id:v<x.v;} }a[N]; int find(int x){return rt[x]==x?x:rt[x]=find(rt[x]);} int merge(int x,int y){ if(!x||!y)return x|y; if(a[y]<a[x])swap(x,y); rs[x]=merge(rs[x],y); if(dis[ls[x]]<dis[rs[x]])swap(ls[x],rs[x]); dis[x]=dis[rs[x]]+1; return x; } int del(int x){ rt[ls[x]]=rt[rs[x]]=rt[x]=merge(ls[x],rs[x]); ls[x]=rs[x]=dis[x]=0; } int main(){ dis[0]=-1; scanf("%d%d",&n,&T); for(int i=1;i<=n;i++){ scanf("%d",&a[i].v); a[i].id=i;rt[i]=i; } while(T--){ int op,x,y; scanf("%d",&op); if(op==1){ scanf("%d%d",&x,&y); if(vis[x]||vis[y])continue; int fx=find(x),fy=find(y); if(fx!=fy)rt[fx]=rt[fy]=merge(fx,fy); } else{ scanf("%d",&x); if(vis[x]){puts("-1");continue;} x=find(x);vis[x]=true; printf("%d\n",a[x].v); del(x); } } return 0; }
割边 https://www.luogu.com.cn/problem/T103481
#include<bits/stdc++.h> using namespace std; const int N=1e6+10; int head[N],nxt[N<<2],to[N<<2]; int n,m,num,tot=1; int low[N],dfn[N]; bool bridge[N<<2]; void add(int x,int y){ nxt[++tot]=head[x]; head[x]=tot; to[tot]=y; } void tarjan(int u,int ine){ low[u]=dfn[u]=++num; for(int i=head[u];i;i=nxt[i]){ int v=to[i]; if(!dfn[v]){ tarjan(v,i); low[u]=min(low[u],low[v]); if(dfn[u]<low[v]) bridge[i]=bridge[i^1]=true; } else if(i!=(ine^1)) low[u]=min(low[u],dfn[v]); }return; } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ int u,v; scanf("%d%d",&u,&v); add(u,v);add(v,u); } for(int i=1;i<=n;i++) if(!dfn[i])tarjan(i,0); int ans=0; for(int i=2;i<tot;i+=2) if(bridge[i])ans++; cout<<ans; return 0; }
割点 https://www.luogu.com.cn/problem/P3388
#include<bits/stdc++.h> using namespace std; const int N=2e4+5,M=4e6+5; int nxt[M],head[N],to[M],cut[N]; int n,m,num,tot; int low[N],dfn[N],rt=0; bool vis[N]; void add(int x,int y){ nxt[++tot]=head[x]; head[x]=tot; to[tot]=y; } void tarjan(int u){ low[u]=dfn[u]=++num; int flag=0; for(int i=head[u];i;i=nxt[i]){ int v=to[i]; if(!dfn[v]){ tarjan(v); low[u]=min(low[u],low[v]); if(dfn[u]<=low[v]){ flag++; if(u!=rt||flag>1)cut[u]=true; } } else low[u]=min(low[u],dfn[v]); } } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ int u,v; scanf("%d%d",&u,&v); add(u,v);add(v,u); } for(int i=1;i<=n;i++) if(!dfn[i])rt=i,tarjan(i); int ans=0; for(int i=1;i<=n;i++) if(cut[i])ans++; printf("%d\n",ans); for(int i=1;i<=n;i++) if(cut[i])printf("%d ",i);puts(""); return 0; }
LCA 全家桶 https://www.luogu.com.cn/problem/P3379
/****************离线Tarjan**********************/ #include<bits/stdc++.h> using namespace std; const int N=5e5+5; int head[N],nxt[N<<1],to[N<<1],tot; int vis[N],fa[N],ans[N]; vector<int>qr[N],qrid[N]; int n,m,s; int find(int x){ if(fa[x]==x)return x; else return fa[x]=find(fa[x]); } void add(int x,int y){ nxt[++tot]=head[x]; head[x]=tot; to[tot]=y; } void addqr(int x,int y,int id){ qr[x].push_back(y); qr[y].push_back(x); qrid[x].push_back(id); qrid[y].push_back(id); } void tarjan(int u){ vis[u]=1; for(int i=head[u];i;i=nxt[i]){ int v=to[i]; if(vis[v])continue; tarjan(v); fa[v]=u; } for(int i=0;i<qr[u].size();i++){ int v=qr[u][i],id=qrid[u][i]; if(vis[v]==2)ans[id]=find(v); } vis[u]=2; } int main(){ scanf("%d%d%d",&n,&m,&s); for(int i=1;i<=n;i++)fa[i]=i; for(int i=1;i<n;i++){ int u,v; scanf("%d%d",&u,&v); add(u,v);add(v,u); } for(int i=1;i<=m;i++){ int u,v; scanf("%d%d",&u,&v); addqr(u,v,i); } tarjan(s); for(int i=1;i<=m;i++) printf("%d\n",ans[i]); return 0; } /***************倍增lca**********************/ #include<bits/stdc++.h> using namespace std; const int N=5e5+10; int n,m,s,f[N][40],dep[N],lg[N],T; int nxt[N<<1],head[N],to[N<<1],tot; void add(int x,int y){ nxt[++tot]=head[x]; head[x]=tot; to[tot]=y; } void dfs(int u,int fa){ dep[u]=dep[fa]+1; f[u][0]=fa; for(int i=1;i<=lg[dep[u]];i++) f[u][i]=f[f[u][i-1]][i-1]; for(int i=head[u];i;i=nxt[i]) if(to[i]!=fa)dfs(to[i],u); } int lca(int u,int v){ if(dep[u]<dep[v])swap(u,v); while(dep[u]>dep[v]) u=f[u][lg[dep[u]-dep[v]]]; if(u==v)return u; for(int k=lg[dep[u]];k>=0;k--) if(f[u][k]!=f[v][k]) u=f[u][k],v=f[v][k]; return f[u][0]; } int main(){ scanf("%d%d%d",&n,&T,&s); for(int i=1;i<n;i++){ int u,v; scanf("%d%d",&u,&v); add(u,v);add(v,u); } lg[0]=-1; for(int i=1;i<=n;i++)lg[i]=lg[i>>1]+1; dfs(s,0); while(T--){ int a,b; scanf("%d%d",&a,&b); printf("%d\n",lca(a,b)); } return 0; } /*************树剖lca*******************/ void lca(int u,int v){ while(top[u]!=top[v]){ if(dep[top[u]]<dep[top[v]])swap(u,v); u=fa[u]; } return dep[u]<dep[v]?u:v; }
点双连通分量
void tarjan(int u){ dfn[u]=low[u]=++num; sk[++top]=u; if(u==rt&&!(now[u])){ dcc[++Dcnt].push_back(u); return; } int flag=0; for(int i=head[u];i;i=nxt[i]){ int v=to[i]; if(!dfn[v]){ tarjan(v); low[u]=min(low[u],low[v]); if(dfn[u]<=low[v]){ flag++; if(x!=rt||flag>1)cut[u]=true; int y;Dcnt++; do{ y=sk[top--]; dcc[Dcnt].push_back(y); }while(y!=v); dcc[Dcnt].push_back(u); } } else low[u]=min(low[u],dfn[v]); } return; } int main(){ for(int i=1;i<=n;i++) if(!dfn[i]){rt=i;tarjan(i);} int ct=Dcnt; for(int i=1;i<=n;i++) if(cut[i])new_id[i]=++ct; for(int i=1;<=Dcnt;i++) for(int j=0;j<dcc[i].size();j++){ int u=dcc[i][j]; if(cut[u]){ add_c(i,new_id[u]) add_c(new_id[u],i); } else col[u]=i; } return 0; }
强连通分量
void tarjan(int u){ vis[sk[++top]=u]=true; dfn[u]=low[u]=++num; for(int i=head[u];i;i=nxt[i]){ int v=to[i]; if(!dfn[v]){ tarjan(v); low[u]=min(low[u],low[v]); } else if(vis[v]) low[u]=min(low[u],dfn[v]); } if(dfn[u]==low[u]){ int v;cnt++; do{ v=sk[top--]; vis[v]=false; col[v]=cnt; }while(u!=v); } } int main(){ for(int u=1;u<=n;u++){ for(int i=head[u];i;i=nxt[i]){ int v=to[i]; if(col[u]==col[v])continue; in[col[v]]++;out[col[u]]++; add_SCC(col[u],col[v]); } } }
KMP https://www.luogu.com.cn/problem/P3375
#include<bits/stdc++.h> using namespace std; const int N=2e6+5; int nxt[N]; char a[N],b[N]; int main(){ scanf("%s\n%s",a+1,b+1); int n=strlen(a+1),m=strlen(b+1); int j=0;nxt[1]=0; for(int i=2;i<=m;i++){ while(j&&b[i]!=b[j+1])j=nxt[j]; if(b[j+1]==b[i])j++; nxt[i]=j; } j=0; for(int i=1;i<=n;i++){ while(j&&b[j+1]!=a[i])j=nxt[j]; if(b[j+1]==a[i])j++; if(j==m){printf("%d\n",i-m+1);j=nxt[j];} } for(int i=1;i<=m;i++)printf("%d ",nxt[i]); return 0; }
可持久化trie https://www.luogu.com.cn/problem/P4735
#include<bits/stdc++.h> using namespace std; const int N=6e5+5; int n,T,tot; int tr[N*24][2],lt[N*24],rt[N*24]; int s[N]; void insert(int i,int k,int p,int q){ if(k<0){ lt[q]=i; return; } int c=s[i]>>k&1; if(p)tr[q][c^1]=tr[p][c^1]; tr[q][c]=++tot; insert(i,k-1,tr[p][c],tr[q][c]); lt[q]=max(lt[tr[q][0]],lt[tr[q][1]]); } int query(int p,int val,int k,int lim){ if(k<0)return s[lt[p]]^val; int c=val>>k&1; if(lt[tr[p][c^1]]>=lim)return query(tr[p][c^1],val,k-1,lim); else return query(tr[p][c],val,k-1,lim); } int main(){ scanf("%d%d",&n,&T); lt[0]=-1; rt[0]=++tot; insert(0,23,0,rt[0]); for(int i=1;i<=n;i++){ int x;scanf("%d",&x); s[i]=s[i-1]^x; rt[i]=++tot; insert(i,23,rt[i-1],rt[i]); } while(T--){ char op[3]; int x,l,r; scanf("%s",op); if(op[0]=='A'){ scanf("%d",&x); rt[++n]=++tot; s[n]=s[n-1]^x; insert(n,23,rt[n-1],rt[n]); } else{ scanf("%d%d%d",&l,&r,&x); printf("%d\n",query(rt[r-1],x^s[n],23,l-1)); } } return 0; }
可持久化并查集 https://www.luogu.com.cn/problem/P3402
#include<bits/stdc++.h> using namespace std; const int N=3.5e6+5; int rt[N],dep[N],fa[N],ls[N],rs[N]; int n,T,now,cnt; void build(int &p,int l,int r){ p=++cnt; if(l==r){fa[p]=l;return;} int mid=l+r>>1; build(ls[p],l,mid); build(rs[p],mid+1,r); } void change(int &p,int q,int l,int r,int x,int F){ p=++cnt; if(l==r){ fa[p]=F; dep[p]=dep[q]; return; } ls[p]=ls[q];rs[p]=rs[q]; int mid=l+r>>1; if(x<=mid)change(ls[p],ls[q],l,mid,x,F); else change(rs[p],rs[q],mid+1,r,x,F); } void add(int p,int l,int r,int x){ if(l==r){++dep[p];return;} int mid=l+r>>1; if(x<=mid)add(ls[p],l,mid,x); else add(rs[p],mid+1,r,x); } int query(int p,int l,int r,int x){ if(l==r)return p; int mid=l+r>>1; if(x<=mid)return query(ls[p],l,mid,x); else return query(rs[p],mid+1,r,x); } int find(int x,int RT){ int F=query(RT,1,n,x); if(x==fa[F])return F; return find(fa[F],RT); } int main(){ scanf("%d%d",&n,&T); build(rt[0],1,n); while(T--){ int op,x,y; scanf("%d",&op); if(op==1){ ++now;rt[now]=rt[now-1]; scanf("%d%d",&x,&y); int fx=find(x,rt[now]); int fy=find(y,rt[now]); if(fa[fx]==fa[fy])continue; if(dep[fx]>dep[fy])swap(fx,fy); change(rt[now],rt[now-1],1,n,fa[fx],fa[fy]); if(dep[fx]==dep[fy])add(rt[now],1,n,fa[fy]); } else if(op==2){ ++now;int k; scanf("%d",&k); rt[now]=rt[k]; } else{ scanf("%d%d",&x,&y); int fx=find(x,rt[now]); int fy=find(y,rt[now]); if(fa[fx]==fa[fy])puts("1"); else puts("0"); now++;rt[now]=rt[now-1]; } } return 0; }
三分 https://www.luogu.com.cn/problem/P3382
#include<bits/stdc++.h> #define eps (1e-6) using namespace std; const int N=15; int n;double a[N]; double f(double x){ double ans =0.0; for(int i=0;i<=n;i++)ans=ans*x+a[i]; return ans; } int main(){ double l,r; scanf("%d",&n); cin>>l>>r; for(int i=0;i<=n;i++)cin>>a[i]; while(l+eps<r){ double lm=l+(r-l)/3.0; double rm=r-(r-l)/3.0; if(f(lm)>f(rm))r=rm; else l=lm; } printf("%.5lf",l); return 0; }
线段树合并 https://www.luogu.com.cn/problem/P4556
#include<bits/stdc++.h> using namespace std; const int N=2e5+5,MX=1e5; int n,T,cnt,num; int nxt[N],to[N],head[N],tot; int siz[N],dep[N],fa[N],son[N]; int dfn[N],rnk[N],top[N]; int rt[N<<5],ls[N<<5],rs[N<<5]; int bh[N<<5],mx[N<<5]; void update(int p){ if(mx[ls[p]]<mx[rs[p]]){ mx[p]=mx[rs[p]]; bh[p]=bh[rs[p]]; } else{ mx[p]=mx[ls[p]]; bh[p]=bh[ls[p]]; } } void add(int x,int y){ nxt[++tot]=head[x]; head[x]=tot; to[tot]=y; } void dfspre(int u,int F){ dep[u]=dep[F]+1; siz[u]=1;fa[u]=F; for(int i=head[u];i;i=nxt[i]){ int v=to[i]; if(v==F)continue; dfspre(v,u); siz[u]+=siz[v]; if(siz[v]>siz[son[u]]) son[u]=v; } } void DFS(int u,int t){ dfn[u]=++cnt;rnk[cnt]=u;top[u]=t; if(son[u])DFS(son[u],t);int v; for(int i=head[u];i;i=nxt[i]) if((v=to[i])!=fa[u]&&v!=son[u])DFS(v,v); } int lca(int u,int v){ while(top[u]!=top[v]){ if(dep[top[u]]<dep[top[v]])swap(u,v); u=fa[top[u]]; } return dep[u]<dep[v]?u:v; } void change(int &p,int l,int r,int x,int k){ if(!p)p=++num; if(l==r){ mx[p]+=k; bh[p]=l; return; } int mid=l+r>>1; if(x<=mid)change(ls[p],l,mid,x,k); else change(rs[p],mid+1,r,x,k); update(p); } int merge(int p,int q,int l,int r){ if(!p||!q)return p|q; if(l==r){ mx[p]+=mx[q]; bh[p]=mx[p]?l:0; return p; } int mid=l+r>>1; ls[p]=merge(ls[p],ls[q],l,mid); rs[p]=merge(rs[p],rs[q],mid+1,r); update(p); return p; } void dfs(int u){ for(int i=head[u];i;i=nxt[i]){ int v=to[i]; if(v==fa[u])continue; dfs(v); rt[u]=merge(rt[u],rt[v],1,MX); } } int main(){ scanf("%d%d",&n,&T); for(int i=1;i<n;i++){ int x,y; scanf("%d%d",&x,&y); add(x,y);add(y,x); } for(int i=1;i<=n;i++)rt[i]=++num; dfspre(1,0); DFS(1,1); while(T--){ int u,v,z; scanf("%d%d%d",&u,&v,&z); int acc=lca(u,v); change(rt[u],1,MX,z,1); change(rt[v],1,MX,z,1); change(rt[acc],1,MX,z,-1); if(fa[acc])change(rt[fa[acc]],1,MX,z,-1); } dfs(1); for(int i=1;i<=n;i++) printf("%d\n",bh[rt[i]]); return 0; }
st表 https://www.luogu.com.cn/problem/P3865
#include<bits/stdc++.h> using namespace std; const int N=1e5+10; int n,T,a[N],lg[N]; int f[N][17]; int main(){ scanf("%d%d",&n,&T); lg[0]=-1; for(int i=1;i<=n;i++)lg[i]=lg[i>>1]+1; for(int i=1;i<=n;i++){ scanf("%d",&a[i]); f[i][0]=a[i]; } int t=lg[n]; for(int j=1;j<=t;j++) for(int i=1;i<=n-(1<<j)+1;i++) f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]); while(T--){ int l,r; scanf("%d%d",&l,&r); int k=lg[r-l+1]; printf("%d\n",max(f[l][k],f[r-(1<<k)+1][k])); } return 0; }
点分治 https://www.luogu.com.cn/problem/P3806
#include<bits/stdc++.h> #define inf (1<<30) using namespace std; const int N=2e5+10; int n,T,cnt,ns,rt; int nxt[N],head[N],to[N],val[N],tot; int me[N],siz[N],Q[N]; bool vis[N],can[N]; struct Node{ int t,d,bl; }a[N]; void add(int x,int y,int z){ nxt[++tot]=head[x]; head[x]=tot;to[tot]=y; val[tot]=z; } void findrt(int u,int F){ me[u]=0;siz[u]=1; for(int i=head[u];i;i=nxt[i]){ int v=to[i]; if(v==F||vis[v])continue; findrt(v,u); siz[u]+=siz[v]; me[u]=max(me[u],siz[v]); } me[u]=max(me[u],ns-siz[u]); if(me[u]<me[rt])rt=u; } void DFS(int u,int F,int dis,int col){ ++cnt; a[cnt].t=u; a[cnt].d=dis; a[cnt].bl=col; for(int i=head[u];i;i=nxt[i]){ int v=to[i],z=val[i]; if(vis[v]||v==F)continue; DFS(v,u,dis+z,col); } } bool cmp(Node A,Node B){ if(A.d!=B.d)return A.d<B.d; } void solve(int u){ cnt=0; ++cnt; a[cnt].t=u; a[cnt].d=0; a[cnt].bl=u; for(int i=head[u];i;i=nxt[i]){ int v=to[i],z=val[i]; if(vis[v])continue; DFS(v,u,z,v); } sort(a+1,a+cnt+1,cmp); for(int i=1;i<=T;i++){ int l=1,r=cnt; while(l<r){ if(a[l].d+a[r].d>Q[i])r--; else if(a[l].d+a[r].d<Q[i])l++; else if(a[r].bl==a[l].bl){ if(a[r].bl==a[r-1].bl)r--; else l++; } else{ can[i]=true; break; } } } return; } void dfs(int u){ vis[u]=true; solve(u); for(int i=head[u];i;i=nxt[i]){ int v=to[i]; if(vis[v])continue; ns=siz[v];rt=0; findrt(v,0); dfs(rt); } } int main(){ scanf("%d%d",&n,&T); for(int i=1;i<n;i++){ int u,v,l; scanf("%d%d%d",&u,&v,&l); add(u,v,l);add(v,u,l); } for(int i=1;i<=T;i++) scanf("%d",&Q[i]); ns=n;me[0]=inf;rt=0; findrt(1,0); dfs(rt); for(int i=1;i<=T;i++) puts(can[i]?"AYE":"NAY"); return 0; }
Dijkstra https://www.luogu.com.cn/problem/P4779
#include<bits/stdc++.h> #define ll long long #define mkr make_pair using namespace std; const int N=4e5+10; int head[N],to[N],val[N],nxt[N]; int tot,n,m,st,d[N];bool v[N]; priority_queue< pair<int,int> >q; void add(int x,int y,int z){ nxt[++tot]=head[x]; to[tot]=y;val[tot]=z; head[x]=tot; } void dijkstra(int st){ memset(d,0x3f,sizeof(d)); memset(v,0,sizeof(v)); d[st]=0;q.push(mkr(0,st)); while(q.size()){ int u=q.top().second;q.pop(); if(v[u])continue;v[u]=true; for(int i=head[u];i;i=nxt[i]){ int v=to[i],z=val[i]; if(d[v]>d[u]+z){ d[v]=d[u]+z; q.push(mkr(-d[v],v)); } } } } int main(){ scanf("%d%d%d",&n,&m,&st); for(int i=1,u,v,l;i<=m;i++){ scanf("%d%d%d",&u,&v,&l); add(u,v,l); } dijkstra(st); for(int i=1;i<=n;i++) if(d[i]!=0x3f3f3f3f)printf("%d ",d[i]); else printf("%lld ",(1LL<<32)-1); return 0; }
差分约束 spfa 负环 https://www.luogu.com.cn/problem/P5960
#include<bits/stdc++.h> #define inf (0x3f3f3f3f) using namespace std; const int N=2e4+10; int n,m; int nxt[N],head[N],to[N],val[N],tot; bool vis[N]; int dis[N],cnt[N]; queue<int>q; void add(int x,int y,int z){ nxt[++tot]=head[x]; head[x]=tot;to[tot]=y; val[tot]=z; } bool spfa(int st){ for(int i=0;i<=n;i++) dis[i]=inf,vis[i]=0,cnt[i]=0; dis[st]=0;vis[st]=true,q.push(st); while(q.size()){ int u=q.front();q.pop(); vis[u]=false; for(int i=head[u];i;i=nxt[i]){ int v=to[i],z=val[i]; if(dis[v]>dis[u]+z){ dis[v]=dis[u]+z; cnt[v]=cnt[u]+1; if(cnt[u]>=n)return false; if(!vis[v]){ vis[v]=true; q.push(v); } } } } return true; } void print(){ for(int i=1;i<=n;i++) printf("%d ",dis[i]); return; } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ int u,v,w; scanf("%d%d%d",&u,&v,&w); add(v,u,w); } for(int i=1;i<=n;i++) add(0,i,0); int flag=spfa(0); if(!flag)puts("NO"); else print(); return 0; }
后缀数组 SA https://www.luogu.com.cn/problem/P3809
#include<bits/stdc++.h> using namespace std; const int N=1e6+5; int n,m; char s[N]; int rk[N<<1],oldrk[N<<1],sa[N],id[N],cnt[N]; int px[N],ht[N]; bool cmp(int x,int y,int w){ return oldrk[x]==oldrk[y]&&oldrk[x+w]==oldrk[y+w]; } int main(){ int p; scanf("%s",s+1); n=strlen(s+1); m=max(n,300); for(int i=1;i<=n;i++)++cnt[rk[i]=s[i]]; for(int i=1;i<=m;i++)cnt[i]+=cnt[i-1]; for(int i=n;i>=1;--i)sa[cnt[rk[i]]--]=i; for(int w=1;;w<<=1,m=p){ p=0; for(int i=n;i>n-w;i--)id[++p]=i; for(int i=1;i<=n;i++)if(sa[i]>w)id[++p]=sa[i]-w; for(int i=1;i<=m;i++)cnt[i]=0; for(int i=1;i<=n;i++)++cnt[px[i]=rk[id[i]]]; for(int i=1;i<=m;i++)cnt[i]+=cnt[i-1]; for(int i=n;i>=1;i--)sa[cnt[px[i]]--]=id[i]; memcpy(oldrk,rk,sizeof(oldrk)); p=0; for(int i=1;i<=n;i++) rk[sa[i]]=cmp(sa[i],sa[i-1],w)?p:++p; if(p==n){ for(int i=1;i<=n;i++)sa[rk[i]]=i; break; } } for(int i=1,k=0;i<=n;i++){ if(k)--k; while(s[i+k]==s[sa[rk[i]-1]+k])++k; ht[rk[i]]=k; } for(int i=1;i<=n;i++)printf("%d ",sa[i]); puts(""); for(int i=1;i<=n;i++)printf("%d ",ht[i]); puts(""); for(int i=1;i<=n;i++)printf("%d ",rk[i]); return 0; }
prim 最小生成树 https://www.luogu.com.cn/problem/P3366
#include<bits/stdc++.h> using namespace std; const int N=5e3+10; int a[N][N],d[N]; bool v[N]; int prim(int n){ memset(d,0x3f,sizeof(d)); d[1]=0; int ans=0; for(int i=1;i<n;i++){ int x=0; for(int j=1;j<=n;j++) if(!v[j]&&(x==0||d[j]<d[x]))x=j; v[x]=1; for(int j=1;j<=n;j++) if(!v[j])d[j]=min(d[j],a[x][j]); } for(int i=1;i<=n;i++) ans+=d[i]; return ans; } int main(){ int n,m; scanf("%d%d",&n,&m); memset(a,0x3f,sizeof(a)); for(int i=1;i<=m;i++){ int u,v,l; scanf("%d%d%d",&u,&v,&l); a[u][v]=a[v][u]=min(a[u][v],l); } printf("%d",prim(n)); return 0; }
kruskal 最小生成树 https://www.luogu.com.cn/problem/P3366
#include<bits/stdc++.h> using namespace std; const int N=2e5+10; int n,m,fa[N],ans; struct edge{ int u,v,w; }a[N]; bool cmp(edge x,edge y){ return x.w<y.w; } int find(int x){ if(fa[x]!=x)return fa[x]=find(fa[x]); return x; } long long kruskal(){ long long ans=0; for(int i=1;i<=m;i++){ int x=a[i].u; int y=a[i].v; int fx=find(x); int fy=find(y); if(fx!=fy)fa[fx]=fy,ans+=a[i].w; } return ans; } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) fa[i]=i; for(int i=1;i<=m;i++) scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].w); sort(a+1,a+m+1,cmp); printf("%lld",kruskal()); return 0; }
dinic https://www.luogu.com.cn/problem/P3376
#include<bits/stdc++.h> #define inf (0x3f3f3f3f) #define ll long long using namespace std; const int N=205,M=2e4+10; int n,m,s,t; int nxt[M],to[M],edge[M],head[M],tot=1; int d[N],cur[N]; queue<int>q; void add(int x,int y,int z){ nxt[++tot]=head[x]; to[tot]=y; head[x]=tot; edge[tot]=z; } bool bfs(){ memset(d,-1,sizeof(d)); while(q.size())q.pop(); q.push(s);d[s]=0; cur[s]=head[s]; while(q.size()){ int u=q.front(),v;q.pop(); for(int i=head[u];i;i=nxt[i]) if(d[v=to[i]]==-1&&edge[i]){ q.push(v); d[v]=d[u]+1; cur[v]=head[v]; if(v==t)return true; } } return false; } ll dfs(int u,ll lim){ if(u==t)return lim; ll flow=0; for(int i=cur[u];i&&flow<lim;i=nxt[i]){ cur[u]=i; int v=to[i]; if(edge[i]!=0&&d[v]==d[u]+1){ ll k=dfs(v,min(1LL*edge[i],lim-flow)); if(!k)d[v]=-1; edge[i]-=k; edge[i^1]+=k; flow+=k; } } return flow; } ll dinic(){ ll flow=0,maxflow=0; while(bfs()) while(flow=dfs(s,inf)) maxflow+=flow; return maxflow; } signed main(){ scanf("%d%d%d%d",&n,&m,&s,&t); for(int i=1;i<=m;i++){ int u,v,l; scanf("%d%d%d",&u,&v,&l); add(u,v,l); add(v,u,0); } printf("%lld",dinic()); return 0; }
EK https://loj.ac/p/101
#include<bits/stdc++.h> #define inf (0x3f3f3f3f) #define int long long using namespace std; const int N=205,M=2e4+10; int n,m,s,t,maxflow; int pre[M],to[M],now[N],val[M],tot=1; int pr[M],incf[N]; bool vis[N]; void add(int x,int y,int z){ pre[++tot]=now[x];now[x]=tot;to[tot]=y;val[tot]=z; pre[++tot]=now[y];now[y]=tot;to[tot]=x;val[tot]=0; } bool bfs(){ memset(vis,0,sizeof(vis)); queue<int>q; q.push(s);vis[s]=true; incf[s]=inf; while(q.size()){ int u=q.front(),v;q.pop(); for(int i=now[u];i;i=pre[i]) if(val[i]&&!vis[to[i]]){ v=to[i]; vis[v]=true; incf[v]=min(incf[u],val[i]); pr[v]=i; q.push(v); if(v==t)return true; } } return false; } void update(){ int u=t; while(u!=s){ int i=pr[u]; val[i]-=incf[t]; val[i^1]+=incf[t]; u=to[i^1]; } maxflow+=incf[t]; } signed main(){ scanf("%lld%lld%lld%lld",&n,&m,&s,&t); for(int i=1;i<=m;i++){ int u,v,l; scanf("%lld%lld%lld",&u,&v,&l); add(u,v,l); } while(bfs())update(); printf("%lld",maxflow); return 0; }
决策单调性(玩具装箱) https://www.luogu.com.cn/problem/P3195
#include<bits/stdc++.h> #define ll long long using namespace std; const int N=5e4+10; int n,L,c[N]; long long f[N],sum[N]; struct Stack{ int l,r,x; Stack(){} Stack(int LL,int RR,int XX){l=LL;r=RR;x=XX;} }; Stack sk[N];int top=0; long long W(int i,int j){ int now=sum[j]-sum[i-1]-L; return 1LL*(j-i+now)*(j-i+now); } int find(int id,int l,int r){ while(l<=r){ int mid=l+r>>1; if(f[id]+W(id+1,mid)<f[sk[top].x]+W(sk[top].x+1,mid))r=mid-1; else l=mid+1; } return l; } int main(){ scanf("%d%d",&n,&L); for(int i=1;i<=n;i++){ scanf("%d",&c[i]); sum[i]=sum[i-1]+c[i]; } int now=1;top=1; sk[top]=Stack(1,n,0); for(int i=1;i<=n;i++){ f[i]=f[sk[now].x]+W(sk[now].x+1,i); while(i<sk[top].l&&f[i]+W(i+1,sk[top].l)<f[sk[top].x]+W(sk[top].x+1,sk[top].l)) --top; int u=find(i,sk[top].l,sk[top].r); sk[top].r=u-1; if(u<=n)sk[++top]=Stack(u,n,i); if(i==sk[now].r)now++; } printf("%lld",f[n]); return 0; }
最长上升子序列 LIS
#include<bits/stdc++.h> using namespace std; const int N=2e5+5; int n,ans,a[N],f[N]; int main(){ cin>>n; for(int i=1;i<=n;i++)cin>>a[i]; for(int i=1;i<=n;i++){ int x=lower_bound(f,f+ans+1,a[i])-f; f[x]=a[i]; if(ans<x)ans=x; } cout<<ans; return 0; }
动态开点 https://www.luogu.com.cn/problem/P1908
#include<bits/stdc++.h> using namespace std; const int N=5e5+5; int n,rt=0,cnt=0; int sum[N<<5],ls[N<<5],rs[N<<5]; void update(int p){ sum[p]=sum[ls[p]]+sum[rs[p]]; } int query(int p,int l,int r,int x,int y){ if(!p)return 0; if(l==x&&r==y)return sum[p]; int mid=l+r>>1; if(y<=mid)return query(ls[p],l,mid,x,y); if(x>mid)return query(rs[p],mid+1,r,x,y); return query(ls[p],l,mid,x,mid)+query(rs[p],mid+1,r,mid+1,y); } void change(int &p,int l,int r,int x,int k){ if(!p)p=++cnt; if(l==r){ sum[p]+=k; return; } int mid=l+r>>1; if(x<=mid)change(ls[p],l,mid,x,k); else change(rs[p],mid+1,r,x,k); update(p); } int main(){ scanf("%d",&n); long long ans=0; for(int i=1;i<=n;i++){ int x; scanf("%d",&x); ans+=query(rt,1,1e9,x+1,1e9); change(rt,1,1e9,x,1); } printf("%lld\n",ans); return 0; }
单调栈 https://www.luogu.com.cn/problem/P5788
#include<bits/stdc++.h> using namespace std; const int N=3e6+10; int n,a[N],f[N]; int sk[N],top; int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); f[n]=0;sk[++top]=n; for(int i=n-1;i>=1;i--){ while(a[i]>=a[sk[top]]&&top)top--; f[i]=sk[top]; sk[++top]=i; } for(int i=1;i<=n;i++) printf("%d ",f[i]); return 0; }
单调队列 https://www.luogu.com.cn/problem/P1886
#include<bits/stdc++.h> using namespace std; const int N=1e6+10; int n,k,a[N],q[N]; int main(){ scanf("%d%d",&n,&k); for(int i=1;i<=n;i++) scanf("%d",&a[i]); int l=1,r=0; for(int i=1;i<=n;i++){ while(l<=r&&a[i]<a[q[r]])r--; q[++r]=i; while(l<=r&&i-q[l]>=k)l++; if(i>=k)printf("%d ",a[q[l]]); }puts(""); l=1,r=0; for(int i=1;i<=n;i++){ while(l<=r&&a[i]>a[q[r]])r--; q[++r]=i; while(l<=r&&i-q[l]>=k)l++; if(i>=k)printf("%d ",a[q[l]]); } return 0; }
树链剖分 重链剖分 https://www.luogu.com.cn/problem/P3384
#include<bits/stdc++.h> #define int long long #define ls p<<1 #define rs p<<1|1 #define lson p<<1,l,mid #define rson p<<1|1,mid+1,r using namespace std; const int N=1e6+5,M=1e6+5; int n,T,rt,P,cnt; int sum[N],tag[N]; int head[N],nxt[M],to[M],tot; int a[N]; int fa[N],siz[N],dep[N],son[N]; int top[N],dfn[N],rnk[N]; void update(int p){ sum[p]=(sum[ls]+sum[rs])%P; } void pushdown(int p,int l,int r){ if(!tag[p])return; int mid=l+r>>1; tag[ls]+=tag[p];tag[ls]%=P; tag[rs]+=tag[p];tag[rs]%=P; sum[ls]+=tag[p]*(mid-l+1);sum[ls]%=P; sum[rs]+=tag[p]*(r-mid);sum[rs]%=P; tag[p]=0; } void add(int u,int v){ nxt[++tot]=head[u]; to[tot]=v; head[u]=tot; } void dfspre(int u,int F){ dep[u]=dep[F]+1; siz[u]=1;fa[u]=F; for(int i=head[u];i;i=nxt[i]){ int v=to[i]; if(v==F)continue; dfspre(v,u); siz[u]+=siz[v]; if(siz[v]>siz[son[v]])son[u]=v; } } void DFS(int u,int t){ dfn[u]=++cnt;rnk[cnt]=u;top[u]=t; if(son[u])DFS(son[u],t);int v; for(int i=head[u];i;i=nxt[i]) if((v=to[i])!=son[u]&&v!=fa[u])DFS(v,v); } void build(int p,int l,int r){ if(l==r){ sum[p]=a[rnk[l]]%P; return; } int mid=l+r>>1; build(lson);build(rson); update(p); } int trsum(int p,int l,int r,int x,int y){ if(x<=l&&y>=r)return sum[p]%P; int ret=0,mid=l+r>>1; pushdown(p,l,r); if(x<=mid)ret=(ret+trsum(lson,x,y))%P; if(y>mid)ret=(ret+trsum(rson,x,y))%P; return ret; } void trchange(int p,int l,int r,int x,int y,int v){ if(x<=l&&y>=r){ tag[p]+=v;tag[p]%=P; sum[p]+=(r-l+1)*v;sum[p]%=P; return; } pushdown(p,l,r); int mid=l+r>>1; if(x<=mid)trchange(lson,x,y,v); if(y>mid)trchange(rson,x,y,v); update(p); } void change(int u,int v,int k){ k%=P; while(top[u]!=top[v]){ if(dep[top[u]]<dep[top[v]])swap(u,v); trchange(1,1,n,dfn[top[u]],dfn[u],k); u=fa[top[u]]; } if(dep[u]>dep[v])swap(u,v); trchange(1,1,n,dfn[u],dfn[v],k); } int query(int u,int v){ int ret=0; while(top[u]!=top[v]){ if(dep[top[u]]<dep[top[v]])swap(u,v); ret+=trsum(1,1,n,dfn[top[u]],dfn[u]);ret%=P; u=fa[top[u]]; } if(dep[u]>dep[v])swap(u,v); ret+=trsum(1,1,n,dfn[u],dfn[v]);ret%=P; return ret; } signed main(){ scanf("%lld%lld%lld%lld",&n,&T,&rt,&P); for(int i=1;i<=n;i++)scanf("%lld",&a[i]); for(int i=1;i<n;i++){ int u,v; scanf("%lld%lld",&u,&v); add(u,v);add(v,u); } dfspre(rt,0); DFS(rt,rt); build(1,1,n); while(T--){ int op,x,y,v; scanf("%lld",&op); if(op==1){ scanf("%lld%lld%lld",&x,&y,&v); change(x,y,v); } else if(op==2){ scanf("%lld%lld",&x,&y); printf("%lld\n",query(x,y)); } else if(op==3){ scanf("%lld%lld",&x,&v); trchange(1,1,n,dfn[x],dfn[x]+siz[x]-1,v); } else{ scanf("%lld",&x); printf("%lld\n",trsum(1,1,n,dfn[x],dfn[x]+siz[x]-1)); } } return 0; }
Splay https://www.luogu.com.cn/problem/P3369
#include<bits/stdc++.h> #define inf (1e9) using namespace std; const int N=5e5+5; struct splay_tree{ int rt,sz=0; int ch[N][2],f[N],siz[N],cnt[N],val[N]; void clear(int u){ch[u][0]=ch[u][1]=siz[u]=cnt[u]=val[u]=0;} int get(int u){return ch[f[u]][1]==u;} void update(int u){ if(u){ siz[u]=cnt[u]; if(ch[u][0])siz[u]+=siz[ch[u][0]]; if(ch[u][1])siz[u]+=siz[ch[u][1]]; } } void rotate(int u){ int fa=f[u],gf=f[fa],wh=get(u); ch[fa][wh]=ch[u][wh^1]; f[ch[fa][wh]]=fa;ch[u][wh^1]=fa; f[fa]=u;f[u]=gf; if(gf)ch[gf][ch[gf][1]==fa]=u; update(fa);update(u); } void splay(int u,int goal){ for(int fa;(fa=f[u])!=goal;rotate(u)) if(f[fa]!=goal)rotate(get(fa)==get(u)?fa:u); if(!goal)rt=u; } int search(int u,int x){ while(val[u]!=x){ if(val[u]>x)if(ch[u][0])u=ch[u][0]; else break; if(val[u]<x)if(ch[u][1])u=ch[u][1]; else break; }return u; } void ins(int x){ if(rt==0){ sz++;ch[sz][0]=ch[sz][1]=f[sz]=0; rt=sz;siz[sz]=cnt[sz]=1;val[sz]=x; return; } int u=search(rt,x); if(val[u]==x){ cnt[u]++; splay(u,0); return; } val[++sz]=x;cnt[sz]=1;f[sz]=u; ch[u][x>val[u]]=sz; splay(sz,0); } int kth(int x){ int u=rt; while(true) if(ch[u][0]&&x<=siz[ch[u][0]])u=ch[u][0]; else{ int tmp=(ch[u][0]?siz[ch[u][0]]:0)+cnt[u]; if(x<=tmp)return val[u]; x-=tmp;u=ch[u][1]; } } int rnk(int x){ int u=search(rt,x); splay(u,0); if(val[u]>=x)return siz[ch[u][0]]+1; else return siz[ch[u][0]]+cnt[u]+1; } int gmost(int u,int op){ if(!op)return search(u,-inf); else return search(u,inf); } int pre_nxt(int x,int op){ int u=search(rt,x); splay(u,0); if((val[u]<x&&!op)||(val[u]>x&&op))return u; else return gmost(ch[u][op],op^1); } int pre(int x){return val[pre_nxt(x,0)];} int nxt(int x){return val[pre_nxt(x,1)];} void del(int x){ int u=search(rt,x); if(val[u]!=x)return; splay(u,0); if(--cnt[u])return; if(!ch[u][0]){ f[ch[u][1]]=0; rt=ch[u][1]; clear(u); }else{ f[ch[u][0]]=0; splay(gmost(ch[u][0],1),0); ch[rt][1]=ch[u][1]; siz[rt]+=siz[ch[u][1]]; if(ch[rt][1])f[ch[rt][1]]=rt; clear(u); } } }tree; int main(){ int T;scanf("%d",&T); while(T--){ int op,x; scanf("%d%d",&op,&x); if(op==1)tree.ins(x); if(op==2)tree.del(x); if(op==3)printf("%d\n",tree.rnk(x)); if(op==4)printf("%d\n",tree.kth(x)); if(op==5)printf("%d\n",tree.pre(x)); if(op==6)printf("%d\n",tree.nxt(x)); } return 0; }
fhq treap 无旋 https://www.luogu.com.cn/problem/P3369
#include<bits/stdc++.h> using namespace std; const int N=2e5+10; int rt,T,cnt; int val[N],siz[N],ls[N],rs[N],pfer[N]; void updata(int p){if(p)siz[p]=siz[ls[p]]+siz[rs[p]]+1;} int New(int x){ int p=++cnt; val[p]=x;siz[p]=1; ls[p]=rs[p]=0; pfer[p]=rand(); return p; } void split(int p,int k,int &x,int &y){ if(!p){x=y=0;return;} if(val[p]<=k){x=p;split(rs[p],k,rs[p],y);} else{y=p;split(ls[p],k,x,ls[p]);} updata(p); } int merge(int x,int y){ if(!x||!y)return x+y; if(pfer[x]>pfer[y]){rs[x]=merge(rs[x],y);updata(x);return x; } else{ls[y]=merge(x,ls[y]);updata(y);return y;} } void ins(int k){ int x,y; split(rt,k-1,x,y); rt=merge(merge(x,New(k)),y); } void del(int k){ int x,y,z; split(rt,k,x,z); split(x,k-1,x,y); if(y)y=merge(ls[y],rs[y]); rt=merge(merge(x,y),z); } int Rank(int k){ int x,y,ans; split(rt,k-1,x,y); ans=siz[x]+1; rt=merge(x,y); return ans; } int kth(int k){ int p=rt; while(true){ if(siz[ls[p]]+1==k)break; else if(siz[ls[p]]+1>k)p=ls[p]; else k-=siz[ls[p]]+1,p=rs[p]; } return val[p]; } int pre(int k){ int x,y,ans,p; split(rt,k-1,x,y); p=x; while(rs[p])p=rs[p]; ans=val[p]; rt=merge(x,y); return ans; } int nxt(int k){ int x,y,ans,p; split(rt,k,x,y); p=y; while(ls[p])p=ls[p]; ans=val[p]; rt=merge(x,y); return ans; } int main(){ srand((unsigned int)time(NULL)); scanf("%d",&T); while(T--){ int op,x; scanf("%d%d",&op,&x); if(op==1)ins(x); if(op==2)del(x); if(op==3)printf("%d\n",Rank(x)); if(op==4)printf("%d\n",kth(x)); if(op==5)printf("%d\n",pre(x)); if(op==6)printf("%d\n",nxt(x)); } return 0; }
最小表示法 https://www.luogu.com.cn/problem/P1368
#include<bits/stdc++.h> using namespace std; const int N=6e6+5; int s[N];int n; int doit(){ for(int i=1;i<=n;i++)s[i+n]=s[i]; int k=0,i=1,j=2; while(i<=n&&j<=n){ for(k=0;k<n&&s[i+k]==s[j+k];k++); if(k==n)break; if(s[i+k]>s[j+k]){i=i+k+1;if(i==j)i++;} else{j=j+k+1;if(i==j)j++;} } int st=min(i,j);return st; } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&s[i]); int st=doit(); for(int i=st;i<=st+n-1;i++)printf("%d ",s[i]); return 0; }
manacher
#include<bits/stdc++.h> using namespace std; const int N=1e6+10; char d[N<<1]; int p[N<<1],cnt,ans; void qr(){ char c=getchar(); if(c=='E')exit(0); d[0]='~',d[cnt=1]='|'; while(c<'a'||c>'z')c=getchar(); while(c>='a'&&c<='z')d[++cnt]=c,d[++cnt]='|',c=getchar(); } int main(){ int num=0; while(true){ memset(p,0,sizeof(p)); qr();ans=0; for(int i=1,r=0,mid=0;i<=cnt;i++){ if(i<=r)p[i]=min(p[(mid<<1)-i],r-i+1); while(d[i-p[i]]==d[i+p[i]])++p[i]; if(p[i]+i>r)r=p[i]+i-1,mid=i; ans=max(ans,p[i]); } printf("Case %d: %d\n",++num,ans-1); } return 0; }
扫描线 https://www.luogu.com.cn/problem/P5490
#include<bits/stdc++.h> #define int long long #define x1 nmsl #define x2 NMSL #define y1 wcnm #define y2 wtnm #define ls p<<1 #define rs p<<1|1 #define lson p<<1,l,mid #define rson p<<1|1,mid+1,r using namespace std; const int N=8e5+5; int n,c[N],tot; int wz[N],MX=0; struct seg{ int x,y1,y2,op; seg(){} seg(int X,int Y1,int Y2,int OP){ x=X;y1=Y1,y2=Y2,op=OP; } }a[N]; int cnt[N<<2],len[N<<2]; bool cmp(seg A,seg B){ return A.x<B.x; } void update(int p,int l,int r){ if(l==MX&&r==MX)return; if(cnt[p])len[p]=wz[r+1]-wz[l]; else len[p]=len[ls]+len[rs]; } void change(int p,int l,int r,int x,int y,int v){ if(x<=l&&y>=r){ cnt[p]+=v; update(p,l,r); return; } int mid=l+r>>1; if(x<=mid)change(lson,x,y,v); if(y>mid)change(rson,x,y,v); update(p,l,r); } signed main(){ scanf("%lld",&n); for(int i=1;i<=n;i++){ int x1,x2,y1,y2; scanf("%lld%lld%lld%lld",&x1,&y1,&x2,&y2); a[++tot]=seg{x1,y1,y2,1};c[tot]=y1; a[++tot]=seg{x2,y1,y2,-1};c[tot]=y2; } sort(c+1,c+tot+1); int m=unique(c+1,c+tot+1)-(c+1); for(int i=1;i<=tot;i++){ int p1=lower_bound(c+1,c+m+1,a[i].y1)-c; int p2=lower_bound(c+1,c+m+1,a[i].y2)-c; wz[p1]=a[i].y1; wz[p2]=a[i].y2; a[i].y1=p1; a[i].y2=p2; MX=max(MX,p2); } sort(a+1,a+tot+1,cmp); long long ans=0; for(int i=1;i<tot;i++){ change(1,1,tot,a[i].y1,a[i].y2-1,a[i].op); ans+=len[1]*(a[i+1].x-a[i].x); } cout<<ans; return 0; }
高斯-约旦消元法 https://www.luogu.com.cn/problem/solution/P3389
#include<bits/stdc++.h> using namespace std; const int N=105; int n;double a[N][N]; int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) for(int j=1;j<=n+1;j++) scanf("%lf",&a[i][j]); for(int i=1;i<=n;i++){ int mx=i; for(int j=i+1;j<=n;j++) if(abs(a[j][i])>abs(a[mx][i]))mx=j; for(int j=1;j<=n+1;j++)swap(a[i][j],a[mx][j]); if(!a[i][i])return puts("No Solution")&0; for(int j=1;j<=n;j++)if(i!=j){ double tmp=a[j][i]/a[i][i]; for(int k=i+1;k<=n+1;k++)a[j][k]-=a[i][k]*tmp; } } for(int i=1;i<=n;i++)printf("%.2lf\n",a[i][n+1]/a[i][i]); return 0; }
普通高斯消元 https://www.luogu.com.cn/problem/solution/P2455
#include<bits/stdc++.h> using namespace std; const int N=53; int n; double a[N][N]; int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) for(int j=1;j<=n+1;j++) scanf("%lf",&a[i][j]); int pl=1; for(int k=1;k<=n;k++){ int mx=pl; for(int i=pl+1;i<=n;i++) if(abs(a[i][k])>abs(a[mx][k]))mx=i; if(a[mx][k]==0)continue; for(int j=1;j<=n+1;j++)swap(a[pl][j],a[mx][j]); for(int i=1;i<=n;i++){ if(i==pl)continue; double mul=a[i][k]/a[pl][k]; for(int j=k+1;j<=n+1;j++) a[i][j]-=a[pl][j]*mul; } ++pl; } if(pl<=n){ while(pl<=n) if(a[pl++][n+1]!=0)return puts("-1")&0; return puts("0")&0; } for(int i=1;i<=n;i++){ printf("x%d=",i); if((int(a[i][n+1]/a[i][i]*100))==0)puts("0.00"); else printf("%.2f\n",a[i][n+1]/a[i][i]); } return 0; }
树套树 线段树套平衡树 https://www.luogu.com.cn/problem/P3380
#include<bits/stdc++.h> #define lson p<<1,l,mid #define rson p<<1|1,mid+1,r #define inf (2147483647) using namespace std; const int N=1.5e6+5; int n,T,cnt,Ans,num; int rt[N],ls[N],rs[N],a[N]; int siz[N],val[N],pfer[N]; void update(int p){ if(!p)return; siz[p]=siz[ls[p]]+siz[rs[p]]+1; } int New(int x){ int p=++cnt; val[p]=x;siz[p]=1; ls[p]=rs[p]=0; pfer[p]=rand()*rand(); return p; } void split(int p,int k,int &x,int &y){ if(!p){x=y=0;return;} if(val[p]<=k){x=p;split(rs[p],k,rs[p],y);} else {y=p;split(ls[p],k,x,ls[p]);} update(p); } int merge(int x,int y){ if(!x||!y)return x|y; if(pfer[x]>pfer[y]){rs[x]=merge(rs[x],y);update(x);return x;} else{ls[y]=merge(x,ls[y]);update(y);return y;} } void ins(int &RT,int k){ int l,r; split(RT,k,l,r); RT=merge(merge(l,New(k)),r); } void del(int &RT,int k){ int x,y,z; split(RT,k,x,z); split(x,k-1,x,y); if(y)y=merge(ls[y],rs[y]); RT=merge(merge(x,y),z); } int rnk(int &RT,int k){ int x,y,ANS; split(RT,k-1,x,y); ANS=siz[x]; RT=merge(x,y); return ANS; } int kth(int &RT,int k){ int p=RT; while("xgy"){ if(siz[ls[p]]+1==k)break; else if(siz[ls[p]]+1>k)p=ls[p]; else k-=siz[ls[p]]+1,p=rs[p]; }return val[p]; } int pre_nxt(int &RT,int k,int op){ int x,y,p,ANS; k-=op; split(RT,k,x,y); p=op?x:y; if(op)while(rs[p])p=rs[p]; else while(ls[p])p=ls[p]; ANS=val[p]; RT=merge(x,y); return ANS; } void build(int p,int l,int r){ if(l==r){ rt[p]=New(a[l]); ins(rt[p],inf);ins(rt[p],-inf); return; } for(int i=l;i<=r;i++)ins(rt[p],a[i]); ins(rt[p],inf);ins(rt[p],-inf); int mid=l+r>>1; build(lson);build(rson); } void change(int p,int l,int r,int x,int v){ del(rt[p],a[x]);ins(rt[p],v); if(l==r)return; int mid=l+r>>1; if(x<=mid)change(lson,x,v); else change(rson,x,v); } void query_pre(int p,int l,int r,int x,int y,int k){ if(x<=l&&y>=r){Ans=max(Ans,pre_nxt(rt[p],k,1));return;} int mid=l+r>>1; if(x<=mid)query_pre(lson,x,y,k); if(y>mid)query_pre(rson,x,y,k); } void query_nxt(int p,int l,int r,int x,int y,int k){ if(x<=l&&y>=r){Ans=min(Ans,pre_nxt(rt[p],k,0));return;} int mid=l+r>>1; if(x<=mid)query_nxt(lson,x,y,k); if(y>mid)query_nxt(rson,x,y,k); } void query_rnk(int p,int l,int r,int x,int y,int k){ if(x<=l&&y>=r){Ans+=rnk(rt[p],k)-1;return;} int mid=l+r>>1; if(x<=mid)query_rnk(lson,x,y,k); if(y>mid)query_rnk(rson,x,y,k); } int ask(int x,int y,int k){ int l=0,r=1e8; while(l<=r){ Ans=1; int mid=l+r>>1; query_rnk(1,1,n,x,y,mid); if(Ans<=k)l=mid+1; else r=mid-1; }return r; } int main(){ srand(time(0)); scanf("%d%d",&n,&T); for(int i=1;i<=n;i++)scanf("%d",&a[i]); build(1,1,n); while(T--){ int op,l,r,k; scanf("%d",&op); if(op==1){ Ans=1; scanf("%d%d%d",&l,&r,&k); query_rnk(1,1,n,l,r,k); printf("%d\n",Ans); }else if(op==2){ scanf("%d%d%d",&l,&r,&k); printf("%d\n",ask(l,r,k)); }else if(op==3){ scanf("%d%d",&l,&r); change(1,1,n,l,r); a[l]=r; }else if(op==4){ Ans=-inf; scanf("%d%d%d",&l,&r,&k); query_pre(1,1,n,l,r,k); printf("%d\n",Ans); }else{ Ans=inf; scanf("%d%d%d",&l,&r,&k); query_nxt(1,1,n,l,r,k); printf("%d\n",Ans); } } return 0; }
树套树 主席树套树状数组 https://www.luogu.com.cn/problem/P2617
#include<bits/stdc++.h> using namespace std; const int N=4e5+10; int n,T,m,tot; int a[N],b[N<<2],rt[N<<7]; int ls[N<<7],rs[N<<7],dat[N<<7],cnt; int LT[N],RT[N],lc,rc; struct{ int l,r,k; int op; }q[N<<2]; void copy(int x,int y,int val){ ls[x]=ls[y]; rs[x]=rs[y]; dat[x]=dat[y]+val; } int build(int l,int r){ int p=++cnt; if(l==r)return p; int mid=l+r>>1; ls[p]=build(l,mid); rs[p]=build(mid+1,r); return p; } int insert(int pre,int l,int r,int x,int val){ int p=++cnt; copy(p,pre,val); if(l==r)return p; int mid=l+r>>1; if(x<=mid)ls[p]=insert(ls[pre],l,mid,x,val); else rs[p]=insert(rs[pre],mid+1,r,x,val); return p; } int query(int l,int r,int k){ if(l==r)return l; int sum=0,mid=l+r>>1; for(int i=1;i<=lc;i++)sum-=dat[ls[LT[i]]]; for(int i=1;i<=rc;i++)sum+=dat[ls[RT[i]]]; if(k<=sum){ for(int i=1;i<=lc;i++)LT[i]=ls[LT[i]]; for(int i=1;i<=rc;i++)RT[i]=ls[RT[i]]; return query(l,mid,k); } else{ for(int i=1;i<=lc;i++)LT[i]=rs[LT[i]]; for(int i=1;i<=rc;i++)RT[i]=rs[RT[i]]; return query(mid+1,r,k-sum); } } void add(int x,int val){ int t=lower_bound(b+1,b+m+1,a[x])-b; for(;x<=N-10;x+=x&-x) rt[x]=insert(rt[x],1,m,t,val); return; } int main(){ scanf("%d%d",&n,&T);tot=0; for(int i=1;i<=n;i++){ scanf("%d",&a[i]); b[++tot]=a[i]; } for(int i=1;i<=T;i++){ char Op[3]; scanf("%s%d%d",Op,&q[i].l,&q[i].r); if(Op[0]=='Q'){ scanf("%d",&q[i].k); q[i].op=0; } else q[i].op=1,b[++tot]=q[i].r; } sort(b+1,b+tot+1); m=unique(b+1,b+tot+1)-b-1; rt[0]=build(1,m); for(int i=1;i<=n;i++)add(i,1); for(int i=1;i<=T;i++){ if(q[i].op==1){ add(q[i].l,-1); a[q[i].l]=q[i].r; add(q[i].l,1); } else{ lc=rc=0; int L=q[i].l-1,R=q[i].r; for(;L;L-=L&-L)LT[++lc]=rt[L]; for(;R;R-=R&-R)RT[++rc]=rt[R]; printf("%d\n",b[query(1,m,q[i].k)]); } } return 0; }
线性基 https://www.luogu.com.cn/problem/P3812
#include<bits/stdc++.h> #define int long long using namespace std; const int N=1e5+5; int n,a[N],p[N],ans; void ins(int x){ for(int i=62;i>=0;i--){ if(!(x>>i))continue; if(!p[i]){p[i]=x;break;} x^=p[i]; } } signed main(){ scanf("%lld",&n); for(int i=1;i<=n;i++){ scanf("%lld",&a[i]); ins(a[i]); } for(int i=62;i>=0;i--)ans=max(ans,ans^p[i]); printf("%lld\n",ans); return 0; }
标记永久化 http://acm.hdu.edu.cn/showproblem.php?pid=4348
#include<bits/stdc++.h> #define int long long using namespace std; const int N=1e5+1; int n,q,tot; int a[N],rt[N],ls[N*19],rs[N*19]; int sum[N*19],add[N*19]; int now=0; int read(){ int a=0,f=1; char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){a=(a<<1)+(a<<3)+c-'0';c=getchar();} return a*f; } void update(int p){ sum[p]=sum[ls[p]]+sum[rs[p]]; } void build(int &p,int l,int r){ //if(!p) p=++tot; if(l==r){ sum[p]=a[l]; return; } int mid=l+r>>1; build(ls[p],l,mid); build(rs[p],mid+1,r); update(p); } void copy(int x,int y){ ls[x]=ls[y]; rs[x]=rs[y]; add[x]=add[y]; sum[x]=sum[y]; } void insert(int &p,int pre,int l,int r,int x,int y,int v){ // if(!p) p=++tot; copy(p,pre); if(x<=l&&y>=r){ add[p]+=v; sum[p]+=1LL*(r-l+1)*v; return; } int mid=l+r>>1; if(x<=mid)insert(ls[p],ls[pre],l,mid,x,y,v); if(y>mid)insert(rs[p],rs[pre],mid+1,r,x,y,v); sum[p]=sum[ls[p]]+sum[rs[p]]+1LL*(r-l+1)*add[p]; return; } long long query(int p,int l,int r,int x,int y,long long v){ if(x<=l&&y>=r)return sum[p]+v*1LL*(r-l+1); int mid=l+r>>1; long long ans=0; if(x<=mid)ans+=query(ls[p],l,mid,x,y,v+add[p]); if(y>mid)ans+=query(rs[p],mid+1,r,x,y,v+add[p]); return ans; } void Clear(){ now=tot=0; for(int i=0;i<=N-1;i++)rt[i]=0; for(int i=0;i<=(n*19)-1;i++) sum[i]=add[i]=ls[i]=rs[i]=0; } signed main(){ while(~scanf("%lld%lld",&n,&q)){ Clear(); for(int i=1;i<=n;i++) a[i]=read(); build(rt[0],1,n); while(q--){ char op[3];int l,r,t; scanf("%s",op); if(op[0]=='B'){ int tmp; tmp=read(); if(tmp!=now){ now=tmp; tot=rt[now+1]-1; } } else if(op[0]=='C'){ ++now; l=read();r=read();t=read(); insert(rt[now],rt[now-1],1,n,l,r,t); } else if(op[0]=='Q'){ l=read();r=read(); printf("%lld\n",query(rt[now],1,n,l,r,0)); } else if(op[0]=='H'){ l=read();r=read();t=read(); printf("%lld\n",query(rt[t],1,n,l,r,0)); } } } return 0; }
四维偏序 http://acm.hdu.edu.cn/showproblem.php?pid=5126
#include<bits/stdc++.h> #define NMsl x1 #define NmSl x2 #define NmsL y1 #define NmSL y2 #define nmsl z1 #define NMSL z2 #define ll long long using namespace std; const int N=4e5+2; int C[N],ans[N]; int cnt,tz[N]; int read(){ int a=0; char c=getchar(); while(c<'0'||c>'9')c=getchar(); while(c>='0'&&c<='9'){a=(a<<1)+(a<<3)+c-'0';c=getchar();} return a; } struct node{ int x,y,z; int op,pos,pt; node(){} node(int X,int Y,int Z,int Op,int Pos,int Pt){ x=X;y=Y;z=Z;op=Op;pos=Pos;pt=Pt; } }a[N],tmp[N],tmp2[N]; bool cmp1(node A,node B){return A.x<B.x;} bool cmp2(node A,node B){return A.y<B.y;} void add(int x,int k){for(;x<=N-1;x+=x&-x)C[x]+=k;} int ask(int x){int sum=0;for(;x;x-=x&-x)sum+=C[x];return sum;} void clear(){cnt=0;memset(ans,0,sizeof(ans));} void cdq2(int l,int r){ if(l>=r)return; int mid=l+r>>1; cdq2(l,mid); cdq2(mid+1,r); int i=l,j=mid+1; for(;j<=r;j++){ for(;i<=mid&&tmp[i].y<=tmp[j].y;i++) if(tmp[i].pt==-1&&tmp[i].pos==0)add(tmp[i].z,1); if(tmp[j].pt==1&&tmp[j].pos)ans[tmp[j].pos]+=ask(tmp[j].z)*tmp[j].op; } while(--i>=l)if(tmp[i].pt==-1&&!tmp[i].pos)add(tmp[i].z,-1); i=l,j=mid+1; int ck=l; while(i<=mid&&j<=r){ if(tmp[i].y<=tmp[j].y) tmp2[ck++]=tmp[i++]; else tmp2[ck++]=tmp[j++]; } while(i<=mid)tmp2[ck++]=tmp[i++]; while(j<=r)tmp2[ck++]=tmp[j++]; for(int k=l;k<=r;k++)tmp[k]=tmp2[k]; } void cdq1(int l,int r){ if(l==r)return; int mid=l+r>>1; cdq1(l,mid); cdq1(mid+1,r); sort(a+l,a+mid+1,cmp1); sort(a+mid+1,a+r+1,cmp1); int i=l,j=mid+1,sd=0; while(i<=mid&&j<=r){ if(a[i].x<=a[j].x){ tmp[++sd]=a[i++]; tmp[sd].pt=-1; if(a[i-1].pos)sd--; }else{ tmp[++sd]=a[j++]; tmp[sd].pt=1; if(!a[j-1].pos)sd--; } } while(i<=mid)tmp[++sd]=a[i++],tmp[sd].pt=-1; while(j<=r)tmp[++sd]=a[j++],tmp[sd].pt=1; cdq2(1,sd); } int main(){ int T; T=read(); while(T--){ clear(); int q,qcnt=0; int zcnt=0; q=read(); for(int i=1;i<=q;i++){ int Op; Op=read(); if(Op==1){ int x,y,z; x=read();y=read();z=read(); ++cnt; a[cnt]=node{x,y,z,0,0,0}; tz[++zcnt]=z; }else{ int x1,y1,z1; int x2,y2,z2; qcnt++; x1=read();y1=read();z1=read(); x2=read();y2=read();z2=read(); a[++cnt]=node{x2,y2,z2,1,qcnt,0}; a[++cnt]=node{x2,y2,z1-1,-1,qcnt,0}; a[++cnt]=node{x2,y1-1,z2,-1,qcnt,0}; a[++cnt]=node{x2,y1-1,z1-1,1,qcnt,0}; a[++cnt]=node{x1-1,y2,z2,-1,qcnt,0}; a[++cnt]=node{x1-1,y2,z1-1,1,qcnt,0}; a[++cnt]=node{x1-1,y1-1,z2,1,qcnt,0}; a[++cnt]=node{x1-1,y1-1,z1-1,-1,qcnt,0}; tz[++zcnt]=z1-1; tz[++zcnt]=z2; } } sort(tz+1,tz+zcnt+1); int fk=unique(tz+1,tz+zcnt+1)-(tz+1); for(int i=1;i<=cnt;i++) a[i].z=lower_bound(tz+1,tz+fk+1,a[i].z)-tz; cdq1(1,cnt); for(int i=1;i<=qcnt;i++) printf("%d\n",ans[i]); } return 0; }
三维偏序 https://www.luogu.com.cn/problem/P3810
#include<bits/stdc++.h> using namespace std; const int N=2e5+11; int n,k,C[N],f[N],cnt[N]; map<long long,int>mp,MP,bk; void add(int x,int v){ for(;x<=k;x+=x&-x)C[x]+=v; } int ask(int x){ int sum=0; for(;x;x-=x&-x)sum+=C[x]; return sum; } struct Node{ int a,b,c,ans,wz; long long hs; }s[N]; bool cmp1(Node A,Node B){ if(A.a==B.a){ if(A.b==B.b)return A.c<B.c; return A.b<B.b; } return A.a<B.a; } bool cmp2(Node A,Node B){ if(A.b==B.b)return A.c<B.c; return A.b<B.b; } void cdq(int l,int r){ if(l==r)return; int mid=l+r>>1; cdq(l,mid);cdq(mid+1,r); sort(s+l,s+mid+1,cmp2); sort(s+mid+1,s+r+1,cmp2); int i=mid+1,j=l; for(;i<=r;i++){ while(s[j].b<=s[i].b&&j<=mid) add(s[j].c,1),j++; s[i].ans+=ask(s[i].c); } for(int i=l;i<j;i++)add(s[i].c,-1); } long long Hash(long long X,long long Y,long long Z){ return X*(N-10)*(N-10)+Y*(N-10)+Z; } int main(){ scanf("%d%d",&n,&k); for(int i=1;i<=n;i++){ scanf("%d%d%d",&s[i].a,&s[i].b,&s[i].c); s[i].hs=Hash(s[i].a,s[i].b,s[i].c); mp[s[i].hs]++; } sort(s+1,s+n+1,cmp1); for(int i=1;i<=n;i++){ bk[s[i].hs]=i; s[i].wz=i; } cdq(1,n); for(int i=1;i<=n;i++){ if(s[i].wz==bk[s[i].hs]){ f[s[i].ans]+=mp[s[i].hs]; } } for(int i=0;i<n;i++)printf("%d\n",f[i]); return 0; }
LCT动态树 https://www.luogu.com.cn/problem/P3690
#include<bits/stdc++.h> using namespace std; const int N=1e5+5; int f[N],ch[N][2],a[N],ret[N],tag[N]; int n,T; bool isrt(int x){return ch[f[x]][0]!=x&&ch[f[x]][1]!=x;} void pushup(int x){ret[x]=a[x]^ret[ch[x][0]]^ret[ch[x][1]];} void pushrev(int x){ if(!x)return; tag[x]^=1; swap(ch[x][0],ch[x][1]); } void pushdown(int x){ if(!tag[x])return; pushrev(ch[x][0]); pushrev(ch[x][1]); tag[x]=0; } void update(int x){if(!isrt(x))update(f[x]);pushdown(x);} int get(int x){return ch[f[x]][1]==x;} void rotate(int x){ int y=f[x],z=f[y],k=get(x); if(!isrt(y))ch[z][ch[z][1]==y]=x; ch[y][k]=ch[x][k^1];f[ch[x][k^1]]=y; ch[x][k^1]=y;f[y]=x;f[x]=z; pushup(y);pushup(x);pushup(z); } void splay(int x){ update(x); for(int fa;fa=f[x],!isrt(x);rotate(x)) if(!isrt(fa))rotate(get(fa)==get(x)?fa:x); } int access(int x){ int p=0; for(;x;p=x,x=f[x]){ splay(x);ch[x][1]=p;pushup(x); }return p; } void mkrt(int x){ access(x);splay(x); swap(ch[x][0],ch[x][1]); tag[x]^=1; } int find(int x){ access(x);splay(x);pushdown(x); while(ch[x][0])pushdown(x=ch[x][0]); splay(x);return x; } void split(int x,int y){ mkrt(x);access(y);splay(y); } void link(int x,int y){ if(find(x)!=find(y)){mkrt(x);f[x]=y;} } void cut(int x,int y){ if(find(x)!=find(y))return; split(x,y); if(ch[y][0]==x&&!ch[x][1]) ch[y][0]=f[x]=0; pushup(x); } void change(int x,int y){a[x]=y;splay(x);} int query(int x,int y){split(x,y);return ret[y];} int main(){ scanf("%d%d",&n,&T); for(int i=1;i<=n;i++)scanf("%d",&a[i]); while(T--){ int op,x,y; scanf("%d%d%d",&op,&x,&y); if(op==0)printf("%d\n",query(x,y)); else if(op==1)link(x,y); else if(op==2)cut(x,y); else change(x,y); } return 0; }
带权并查集 https://www.luogu.com.cn/problem/P1196
#include<bits/stdc++.h> using namespace std; const int N=3e4+5; int T,fa[N],d[N],siz[N]; int find(int x){ if(x==fa[x])return x; int p=find(fa[x]); d[x]+=d[fa[x]]; return fa[x]=p; } void merge(int x,int y){ x=find(x);y=find(y); fa[x]=y;d[x]=siz[y]; siz[y]+=siz[x]; } int main(){ for(int i=1;i<=N-5;i++) fa[i]=i,siz[i]=1; int T; scanf("%d",&T); while(T--){ char op[3];int x,y; scanf("%s %d %d",op,&x,&y); if(op[0]=='M'){ merge(x,y); }else{ int fx=find(x),fy=find(y); if(fx!=fy)puts("-1"); else printf("%d\n",abs(d[x]-d[y])-1); } } return 0; }
Lucas定理 https://www.luogu.com.cn/problem/P3807
#include<bits/stdc++.h> #define ll long long using namespace std; const int N=1e5; int p; int ksm(int a,int b){ int ans=1%p; for(;b;b>>=1){ if(b&1)ans=1LL*ans*a%p; a=1LL*a*a%p; } return ans%p; } int C(int n,int m){ if(n<m)return 0; int r1=1,r2=1,r3=1; for(int i=1;i<=m;i++)r3=1LL*r3*i%p; for(int i=1;i<=n;i++)r1=1LL*r1*i%p; for(int i=1;i<=n-m;i++)r2=1LL*r2*i%p; return 1LL*r1*ksm(r2,p-2)%p*ksm(r3,p-2)%p; } int Lucas(int n,int m){ if(m==0)return 1; return 1LL*Lucas(n/p,m/p)%p*C(n%p,m%p)%p; } int main(){ int T; scanf("%d",&T); while(T--){ int n,m; scanf("%d%d%d",&n,&m,&p); printf("%d\n",Lucas(n+m,n)); } return 0; }
Splay 区间操作 https://www.luogu.com.cn/problem/P4036
#include<bits/stdc++.h> #define int long long using namespace std; const int B=31,mod=998244353,N=6e5+5; char s[N];int root,sz,T; int p[N],val[N],hs[N],f[N],siz[N],ch[N][2]; int get(int u){return ch[f[u]][1]==u;} void update(int u){ if(!u)return;siz[u]=1; if(ch[u][0])siz[u]+=siz[ch[u][0]]; if(ch[u][1])siz[u]+=siz[ch[u][1]]; hs[u]=(hs[ch[u][0]]+1LL*val[u]*p[siz[ch[u][0]]]%mod)%mod+1LL*hs[ch[u][1]]*p[siz[ch[u][0]]+1]%mod; hs[u]%=mod; } void build(int l,int r,int u){ if(l>r)return; int mid=l+r>>1; if(u<=mid)ch[u][1]=mid; else ch[u][0]=mid; f[mid]=u;siz[mid]=1; if(l==r)return; build(l,mid-1,mid); build(mid+1,r,mid); update(mid); } void rotate(int u){ int fa=f[u],gf=f[fa],wh=get(u); ch[fa][wh]=ch[u][wh^1]; f[ch[fa][wh]]=fa; ch[u][wh^1]=fa; f[u]=gf;f[fa]=u; if(gf)ch[gf][ch[gf][1]==fa]=u; update(fa);update(u); } void splay(int u,int goal){ for(int fa;(fa=f[u])!=goal;rotate(u)) if(f[fa]!=goal)rotate(get(fa)==get(u)?fa:u); if(!goal)root=u; } int find(int x){ int u=root; while("cnyz ak ioi"){ if(siz[ch[u][0]]+1==x)return u; if(siz[ch[u][0]]+1<x){ x-=siz[ch[u][0]]+1; u=ch[u][1]; }else u=ch[u][0]; } } void ins(int x,int v){ int pre=find(x+1),nxt=find(x+2); splay(pre,0); splay(nxt,pre); ch[nxt][0]=++sz; f[sz]=nxt;hs[sz]=val[sz]=v; splay(sz,0); } int Hash(int l,int r){ int x=find(l),y=find(r+2); splay(x,0);splay(y,x); int fx=ch[y][0];return hs[fx]; } signed main(){ scanf("%s",s+1); int n=strlen(s+1);p[0]=1; for(int i=1;i<=n*2;i++)p[i]=p[i-1]*B%mod; for(int i=2;i<=n+1;i++)val[i]=hs[i]=s[i-1]-'a'+1; build(1,n+2,root); root=(n+3)>>1,sz=n+2; scanf("%lld",&T); while(T--){ char op[2],c[2];int x,y; scanf("%s",op); if(op[0]=='Q'){ scanf("%lld%lld",&x,&y); if(x>y)swap(x,y); int l=0,r=sz-y-1; // cout<<sz<<' '<<y<<endl; while(l<=r){ int mid=l+r>>1; // cout<<mid<<endl; if(Hash(x,x+mid-1)==Hash(y,y+mid-1))l=mid+1; else r=mid-1; } printf("%lld\n",r); }else if(op[0]=='R'){ scanf("%lld %s",&x,c); char cs=c[0]; splay(find(x+1),0); val[root]=cs-'a'+1; update(root); }else if(op[0]=='I'){ scanf("%lld %s",&x,c); char cs=c[0]; ins(x,cs-'a'+1); } }return 0; }
莫队 https://www.luogu.com.cn/problem/P1494
#include<bits/stdc++.h> #define int long long using namespace std; const int N=2e5+5; int n,T,t,cnt[N],a[N]; int ans; struct seg{int l,r,id;}q[N],ret[N]; bool cmp(seg A,seg B){ if(A.l/t!=B.l/t)return A.l/t<B.l/t; if((A.l/t)&1)return A.r<B.r; return A.r>B.r; } int gcd(int a,int b){return b?gcd(b,a%b):a;} void add(int x){ ans-=(1LL*cnt[a[x]]*(cnt[a[x]]-1))>>1; cnt[a[x]]++; ans+=(1LL*cnt[a[x]]*(cnt[a[x]]-1))>>1; } void del(int x){ ans-=(1LL*cnt[a[x]]*(cnt[a[x]]-1))>>1; cnt[a[x]]--; ans+=(1LL*cnt[a[x]]*(cnt[a[x]]-1))>>1; } signed main(){ scanf("%lld%lld",&n,&T); for(int i=1;i<=n;i++)scanf("%lld",&a[i]); for(int i=1;i<=T;i++){ scanf("%lld%lld",&q[i].l,&q[i].r); q[i].id=i; } t=sqrt(T); sort(q+1,q+T+1,cmp); int l=1,r=0; for(int i=1;i<=T;i++){ while(l<q[i].l)del(l++); while(l>q[i].l)add(--l); while(r<q[i].r)add(++r); while(r>q[i].r)del(r--); int up=ans,down=(r-l+1)*(r-l)>>1; if(r==l){ ret[q[i].id].l=0; ret[q[i].id].r=1; continue; } int G=gcd(up,down); up/=G;down/=G; ret[q[i].id].l=up; ret[q[i].id].r=down; } for(int i=1;i<=T;i++) printf("%lld/%lld\n",ret[i].l,ret[i].r); return 0; }
欧拉回路 无向图
#include<bits/stdc++.h> using namespace std; const int M=4e5+10; int n,m,tot=1,t; int ans[M],sk[M],top; int nxt[M],head[M],to[M]; bool vis[M]; void add(int x,int y){ nxt[++tot]=head[x]; head[x]=tot;to[tot]=y; } void euler(){ sk[++top]=1; while(top){ int u=sk[top],i=head[u]; while(i&&vis[i])i=nxt[i]; if(i)sk[++top]=to[i],head[u]=nxt[i],vis[i]=vis[i^1]=true; else top--,ans[++t]=u; } } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ int u,v; scanf("%d%d",&u,&v); add(u,v);add(v,u); } euler(); for(int i=t;i;i--)printf("%d\n",ans[i]); return 0; }
欧拉路径 有向图 https://www.luogu.com.cn/problem/P7771
#include<bits/stdc++.h> using namespace std; const int N=4e5+5; int n,m,pr[N]; vector<int>G[N],id[N]; int in[N],out[N];bool vis[N]; int sk[N],top; void dfs(int u){ int sze=G[u].size(); for(int i=pr[u];i<sze;i=max(i+1,pr[u])){ int v=G[u][i],ine=id[u][i]; if(!vis[ine]){ vis[ine]=true; pr[u]=i+1; dfs(v); } } sk[++top]=u; } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ int u,v; scanf("%d%d",&u,&v); G[u].push_back(v); id[u].push_back(i); in[v]++;out[u]++; } for(int i=1;i<=n;i++)sort(G[i].begin(),G[i].end()); int st=0,ed=0,cnt=0; for(int i=1;i<=n;i++){ if(in[i]==out[i])continue; if(in[i]==out[i]+1)ed=i,cnt++; if(in[i]+1==out[i])st=i,cnt++; } if((cnt!=0&&cnt!=2))return puts("No")&0; if(!cnt)st=1;dfs(st); while(top)printf("%d ",sk[top--]); return 0; }
整体二分 https://www.luogu.com.cn/problem/P7424
#include<bits/stdc++.h> using namespace std; const int N=6e5+5; struct Que{ int id,l,r,s,tim; Que(){id=0;} }q[N],lq[N],rq[N]; int c[N],MX,res[N]; void add(int x,int k){ for(;x<=MX;x+=x&-x)c[x]+=k; } int ask(int x){ int S=0; for(;x;x-=x&-x)S+=c[x]; return S; } int n,m,ans[N]; void solve(int L,int R,int l,int r){ if(l>r)return; if(L==R){ for(int i=l;i<=r;i++)ans[q[i].id]=L; return; } int mid=L+R>>1,lt=0,rt=0; for(int i=l;i<=r;i++){ if(!q[i].id){ if(q[i].tim<=mid)lq[++lt]=q[i],add(q[i].l,1); else rq[++rt]=q[i]; }else{ int k=ask(q[i].r)-ask(q[i].l-1); if(q[i].s<=k)lq[++lt]=q[i]; else q[i].s-=k,rq[++rt]=q[i]; } } for(int i=1;i<=lt;i++)if(!lq[i].id)add(lq[i].l,-1); for(int i=1;i<=lt;i++)q[l+i-1]=lq[i]; for(int i=1;i<=rt;i++)q[l+lt+i-1]=rq[i]; solve(L,mid,l,l+lt-1); solve(mid+1,R,l+lt,r); } int main(){ //freopen("ex1.in","r",stdin); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ scanf("%d%d%d",&q[m+i].l,&q[m+i].r,&q[m+i].s); q[m+i].id=i; MX=max(MX,q[m+i].r); } MX=2e5; for(int i=1;i<=m;i++){ scanf("%d",&q[i].l); q[i].tim=i;q[i].id=0; } solve(1,m+1,1,n+m); for(int i=1;i<=n;i++)res[ans[i]]++; for(int i=1;i<=m;i++)printf("%d\n",res[i]); return 0; } /* 3 5 1 3 2 4 5 5 3 5 5 5 4 5 3 1 */
二维hash https://www.luogu.com.cn/problem/P4398
#include<bits/stdc++.h> using namespace std; const int N=55; const int B1=31,B2=37; const int P=1e9+7; int h[N][N],a[N][N],H[N][N],b[N][N],n; int pw1[N],pw2[N]; map<int,int>mp; int get(int op,int i,int j,int k,int l){ if(op==0){ int V1=h[i][j]; int V2=1LL*h[i][l-1]*pw1[j-l+1]%P; int V3=1LL*h[k-1][j]*pw2[i-k+1]%P; int V4=1LL*h[k-1][l-1]*pw1[i-k+1]%P*pw2[j-l+1]%P; return ((1LL*V1-V2-V3+V4)%P+P)%P; }else{ int V1=H[i][j]; int V2=1LL*H[i][l-1]*pw1[j-l+1]%P; int V3=1LL*H[k-1][j]*pw2[i-k+1]%P; int V4=1LL*H[k-1][l-1]*pw1[i-k+1]%P*pw2[j-l+1]%P; return ((1LL*V1-V2-V3+V4)%P+P)%P; } } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)scanf("%d",&a[i][j]); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)scanf("%d",&b[i][j]); pw1[0]=pw2[0]=1; for(int i=1;i<=n;i++){ pw1[i]=1LL*pw1[i-1]*B1%P; pw2[i]=1LL*pw2[i-1]*B2%P; } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) h[i][j]=(1LL*h[i][j-1]*B1%P+a[i][j])%P; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) h[i][j]+=1LL*h[i-1][j]*B2%P; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) H[i][j]=(1LL*H[i][j-1]*B1%P+b[i][j])%P; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) H[i][j]+=1LL*H[i-1][j]*B2%P; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) for(int len=1;len<=n;len++){ if(i+len-1>n||j+len-1>n)continue; mp[get(0,i+len-1,j+len-1,i,j)]=true; } int ans=0; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) for(int len=1;len<=n;len++){ if(i+len-1>n||j+len-1>n)continue; if(mp[get(1,i+len-1,j+len-1,i,j)])ans=max(ans,len); } printf("%d\n",ans); return 0; }
大可并堆板子 https://www.luogu.com.cn/problem/P3273
#include<bits/stdc++.h> using namespace std; const int N=6e5+5; int n,m,add; int ls[N],rs[N],dis[N],val[N],fa[N]; int f[N],siz[N],tag[N]; int find(int x){ return f[x]==x?x:f[x]=find(f[x]); }//hht 下面好大 void pushup(int x){ if(!x)return; if(dis[x]!=dis[rs[x]]+1){ dis[x]=dis[rs[x]]+1; pushup(fa[x]); } } int merge(int x,int y){ if(!x||!y)return x|y; if(val[x]<val[y])swap(x,y); rs[x]=merge(rs[x],y); fa[rs[x]]=x;fa[ls[x]]=x; if(dis[rs[x]]>dis[ls[x]])swap(ls[x],rs[x]); pushup(x);return x; } void pushdown(int p,int v){ if(!p)return; val[p]+=v; pushdown(ls[p],v); pushdown(rs[p],v); } multiset<int>s; int main(){ //freopen("ex.in","r",stdin); scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&val[i]); siz[i]=1;f[i]=i; s.insert(val[i]); } scanf("%d",&m); while(m--){ char op[5];int x,y,v; scanf("%s",op); if(op[0]=='U'){ scanf("%d%d",&x,&y); x=find(x);y=find(y); if(x==y)continue; if(siz[x]>siz[y])swap(x,y); pushdown(x,tag[x]-tag[y]); f[x]=f[y]=merge(x,y); if(f[x]==x){ s.erase(s.find(val[y]+tag[y])); tag[x]=tag[y]; siz[x]+=siz[y]; tag[y]=siz[y]=0; }else{ s.erase(s.find(val[x]+tag[y])); siz[y]+=siz[x]; tag[x]=siz[x]=0; } }else if(op[0]=='A'){ if(op[1]=='1'){ scanf("%d%d",&x,&v); if(x==find(x)){ fa[ls[x]]=fa[rs[x]]=0; y=merge(ls[x],rs[x]); s.erase(s.find(val[x]+tag[x])); val[x]+=v; fa[x]=ls[x]=rs[x]=0; dis[x]=1; f[x]=f[y]=merge(x,y); s.insert(val[f[x]]+tag[x]); if(f[x]==y){ tag[y]=tag[x]; siz[y]=siz[x]; tag[x]=siz[x]=0; } }else{ fa[ls[x]]=fa[rs[x]]=fa[x]; if(ls[fa[x]]==x)ls[fa[x]]=merge(ls[x],rs[x]); else rs[fa[x]]=merge(ls[x],rs[x]); val[x]+=v; fa[x]=ls[x]=rs[x]=0; dis[x]=1; y=find(x); f[x]=f[y]=merge(x,y); if(f[x]==x){ s.erase(s.find(val[y]+tag[y])); s.insert(val[x]+tag[y]); tag[x]=tag[y]; siz[x]=siz[y]; siz[y]=tag[y]=0; } } } else if(op[1]=='2'){ scanf("%d%d",&x,&v); x=find(x); s.erase(s.find(val[x]+tag[x])); tag[x]+=v; s.insert(val[x]+tag[x]); }else{ scanf("%d",&v);add+=v; } }else if(op[1]=='1'){ scanf("%d",&x); printf("%d\n",val[x]+tag[find(x)]+add); }else if(op[1]=='2'){ scanf("%d",&x); x=find(x); printf("%d\n",val[x]+tag[x]+add); }else{ printf("%d\n",*s.rbegin()+add); } } return 0; }
匈牙利 二分图最大匹配 https://www.luogu.com.cn/problem/P3386
#include<bits/stdc++.h> using namespace std; const int N=1e5+5; int head[N],nxt[N],to[N],tot; int vis[N],tag,path[N],n,m,e,ans; void add(int x,int y){nxt[++tot]=head[x];head[x]=tot;to[tot]=y;} bool dfs(int u){ for(int i=head[u];i;i=nxt[i]){ int v=to[i]; if(vis[v]==tag)continue; vis[v]=tag; if(!path[v]||dfs(path[v])){path[v]=u;return 1;} } return 0; } int main(){ scanf("%d%d%d",&n,&m,&e); for(int i=1;i<=e;i++){int x,y;scanf("%d%d",&x,&y);add(x,y);} for(int i=1;i<=n;i++){tag++;if(dfs(i))ans++;} printf("%d\n",ans); }
dp求树的直径
void dp(int x){ v[x]=1; for(register int i=head[x];i;i=nxt[i]){ int y=to[i],Val=edge[i]; if(v[y])continue; dp(y); ans=max(ans,d[x]+d[y]+Val); d[x]=max(d[x],d[y]+Val); } }
dfs求树的重心
void findrt(int u,int F){ me[u]=0;siz[u]=1; for(int i=now[u];i;i=pre[i]){ int v=to[i]; if(v==F||vis[v])continue; findrt(v,u); siz[u]+=siz[v]; me[u]=max(me[u],siz[v]); } me[u]=max(me[u],ns-siz[u]); if(me[u]<me[rt])rt=u; }
基环树找奇环
void find(int u){ dfn[u]=++idx; for(int i=head[u];i;i=nxt[i]){ int v=to[i]; if(v==dad[u])continue; if(dfn[v]){ if(dfn[v]<dfn[u])continue; lp[++cnt]=v; vis[lp[cnt]]=true; for(;v!=u;v=dad[v]) lp[++cnt]=dad[v],vis[lp[cnt]]=true; }else dad[v]=u,find(v); } }
数位dp https://www.luogu.com.cn/problem/P4999
#include<bits/stdc++.h> #define int long long using namespace std; const int mod=1e9+7,N=22; int len,a[N],f[N][N*11]; int dfs(int pos,int sum,bool fl,int lim){ if(!pos)return sum%mod; if(!lim&&f[pos][sum]!=-1)return f[pos][sum]; int ret=0,mx=lim?a[pos]:9; for(int i=0;i<=mx;i++) if(fl&&i==0)ret+=dfs(pos-1,0,1,lim&&i==mx),ret%=mod; else ret+=dfs(pos-1,sum+i,0,lim&&i==mx),ret%=mod; if(!lim&&!fl)f[pos][sum]=ret%mod; return ret; } int solve(int x){ len=0; while(x)a[++len]=x%10,x/=10; return dfs(len,0,1,1)%mod; } signed main(){ int T;scanf("%lld",&T); memset(f,-1,sizeof(f)); while(T--){ int l,r; scanf("%lld%lld",&l,&r); printf("%lld\n",((solve(r)-solve(l-1)%mod+mod)%mod)); } return 0; }
AC 自动机 https://www.luogu.com.cn/problem/P5357
#include<bits/stdc++.h> using namespace std; const int N=2e5+5,M=2e6+5; char s[M];int n,op[N],sum[N]; int tr[N][27],fail[N],tot; int head[N],nxt[N<<1],to[N<<1],cnt; void add(int x,int y){ nxt[++cnt]=head[x]; head[x]=cnt; to[cnt]=y; } void ins(char *s,int x){ int m=strlen(s),p=0; for(int i=0;i<m;i++){ int l=s[i]-'a'; if(!tr[p][l])tr[p][l]=++tot; p=tr[p][l]; }op[x]=p; } queue<int>q; void build_AC(){ for(int i=0;i<26;i++) if(tr[0][i]){ fail[tr[0][i]]=0; q.push(tr[0][i]); } while(q.size()){ int u=q.front();q.pop(); for(int i=0;i<26;i++){ if(tr[u][i]){ fail[tr[u][i]]=tr[fail[u]][i]; q.push(tr[u][i]); } else tr[u][i]=tr[fail[u]][i]; } } } void work(char *s){ int p=0,m=strlen(s); for(int i=0;i<m;i++){ p=tr[p][s[i]-'a']; sum[p]++; } } void dfs(int u){ for(int i=head[u];i;i=nxt[i]){ int v=to[i]; dfs(v);sum[u]+=sum[v]; } } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%s",s); ins(s,i); } build_AC(); scanf("%s",s);work(s); for(int i=1;i<=tot;i++)add(fail[i],i); dfs(0); for(int i=1;i<=n;i++)printf("%d\n",sum[op[i]]); return 0; }
cdq分治斜率优化 https://www.luogu.com.cn/problem/P4655
#include<bits/stdc++.h> #define int long long using namespace std; const int N=2e5+5; const double INF=1e20; int h[N],w[N],f[N],s[N],q[N],n; struct node{int id,x,y,k;}a[N],b[N]; bool operator < (node A,node B){return A.x==B.x?A.y<B.y:A.x<B.x;} int X(int j){return a[j].x;} int Y(int j){return a[j].y;} double slope(int i,int j){ if(X(i)==X(j))return Y(i)<Y(j)?INF:-INF; return double(Y(i)-Y(j))*1.0/(double(X(i)-X(j))*1.0); } bool cmp(node A,node B){return A.k<B.k;} void cdq(int l,int r){ if(l==r){ int x=a[l].id; a[l].y=f[x]-s[x]+h[x]*h[x]; return; } int mid=l+r>>1; int L=l,R=mid+1,hd=1,tl=0; for(int i=l;i<=r;i++) a[i].id<=mid?b[L++]=a[i]:b[R++]=a[i]; for(int i=l;i<=r;i++)a[i]=b[i]; cdq(l,mid); for(int i=l;i<=mid;i++){ while(hd<tl&&slope(q[tl-1],q[tl])>=slope(q[tl],i))tl--; q[++tl]=i; } for(int i=mid+1;i<=r;i++){ while(hd<tl&&slope(q[hd],q[hd+1])<=a[i].k)hd++; if(hd<=tl){ int x=a[i].id,j=q[hd]; f[x]=min(f[x],a[j].y-a[i].k*a[j].x+s[x-1]+h[x]*h[x]); } } cdq(mid+1,r); int j=l-1; L=l;R=mid+1; while(L<=mid&&R<=r)b[++j]=a[L]<a[R]?a[L++]:a[R++]; while(L<=mid)b[++j]=a[L++]; while(R<=r)b[++j]=a[R++]; for(int i=l;i<=r;i++)a[i]=b[i]; } signed main(){ scanf("%lld",&n); for(int i=1;i<=n;i++)scanf("%lld",&h[i]); for(int i=1;i<=n;i++){ scanf("%lld",&w[i]); s[i]=s[i-1]+w[i]; } for(int i=1;i<=n;i++){ a[i].id=i; a[i].k=2*h[i]; a[i].x=h[i]; } sort(a+1,a+n+1,cmp); memset(f,0x3f,sizeof(f)); f[1]=0;cdq(1,n); printf("%lld\n",f[n]); return 0; }
模拟退火 https://www.luogu.com.cn/problem/P1337
#include<bits/stdc++.h> using namespace std; const int N=1e3+5,MX=RAND_MAX; const double dt=0.97; double T,T0; int n;double ansx,ansy,ans; struct Node{int x,y,w;}a[N]; double calc(double x,double y){ double ret=0; for(int i=1;i<=n;i++){ double X=x-a[i].x,Y=y-a[i].y; ret+=sqrt(X*X+Y*Y)*(double)a[i].w; }return ret; } void Anneal(){ double x=ansx,y=ansy; T=2000,T0=1e-15; while(T>T0){ double X=x+double((rand()<<1)-MX)*T; double Y=y+double((rand()<<1)-MX)*T; double ret=calc(X,Y),delta=ret-ans; if(delta<0){x=ansx=X,y=ansy=Y;ans=ret;} else if(exp(-delta/T)*MX>rand())x=X,y=Y; T*=dt; } } int main(){ srand(19260817); srand(rand());srand(rand()); srand(rand());srand(rand()); scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].w); ansx+=a[i].x,ansy+=a[i].y; } ansx/=(double)n,ansy/=(double)n; ans=calc(ansx,ansy); for(int i=1;i<=20;i++)Anneal(); return printf("%.3lf %.3lf\n",ansx,ansy)&0; }
高维前缀和 https://www.luogu.com.cn/problem/AT4168
#include<bits/stdc++.h> using namespace std; const int N=3e5+5; int n,mx[N],ne[N]; int main(){ scanf("%d",&n); for(int i=0;i<(1<<n);i++) scanf("%d",&mx[i]); for(int j=0;j<n;j++) for(int i=0;i<(1<<n);i++) if((i>>j)&1){ int x=i^(1<<j); if(mx[x]>mx[i]){ ne[i]=max(mx[i],ne[x]); mx[i]=mx[x]; }else if(mx[x]==mx[i]) ne[i]=mx[i]; else ne[i]=max(ne[i],mx[x]); } int ans=0; for(int i=1;i<(1<<n);i++){ ans=max(ans,mx[i]+ne[i]); printf("%d\n",ans); } return 0; }
BSGS https://www.luogu.com.cn/problem/P3846
#include<bits/stdc++.h> #define int long long using namespace std; int p,a,b; int fpow(int a,int b,int mod){ int ret=1; for(;b;b>>=1){ if(b&1)ret=1LL*ret*a%mod; a=1LL*a*a%mod; }return ret; } map<int,int>hs; int bsgs(int a,int b,int p){ b%=p;int t=sqrt(p)+1; for(int i=0;i<t;i++) hs[b*fpow(a,i,p)%p]=i; a=fpow(a,t,p); if(!a)return b==0?1:-1; for(int i=1;i<=t;i++){ int val=fpow(a,i,p); int j=hs.find(val)==hs.end()?-1:hs[val]; if(j>=0&&i*t-j>=0)return i*t-j; }return -1; } signed main(){ cin>>p>>a>>b; int ans=bsgs(a,b,p); if(ans==-1)puts("no solution"); else cout<<ans<<endl; return 0; }
EXCRT CRT https://www.luogu.com.cn/problem/P4777
#include<bits/stdc++.h> #define int long long using namespace std; int mul(int a,int b,int mod){ int ret=0; for(;b;b>>=1){ if(b&1)(ret+=a)%=mod; (a*=2)%=mod; }return ret; } int gcd(int a,int b){return b?gcd(b,a%b):a;} void exgcd(int a,int b,int &x,int &y){ if(b==0){x=1,y=0;return;} exgcd(b,a%b,y,x),y-=a/b*x; } signed main(){ int n,a,b,c,d; cin>>n>>a>>b; for(int i=2;i<=n;i++){ cin>>c>>d; int dt=((d-b)%c+c)%c,D=gcd(a,c),L=a/D*c,x=0,y=0; exgcd(a,c,x,y);x=mul(x,dt/D,c/D); b=(b+a*x)%L;a=L; } return cout<<((b%a)+a)%a<<endl,0; }
李超线段树 https://www.luogu.com.cn/problem/CF932F
#include<bits/stdc++.h> #define int long long using namespace std; const int N=4.1e5+5,DT=1e5+5,MX=DT<<1,INF=1e15; vector<int>G[N]; int t[N<<4],ls[N<<4],rs[N<<4],rt[N<<4],cnt; int k[N],b[N],A[N],B[N],f[N],n; int w(int p,int x){return k[p]*x+b[p];} void update(int &p,int l,int r,int x){ if(!p){p=++cnt;t[p]=x;return;} int mid=l+r>>1; if(w(t[p],mid)>w(x,mid))swap(t[p],x); if(w(t[p],l)<=w(x,l)&&w(t[p],r)<=w(x,r))return; if(w(t[p],l)>w(x,l))update(ls[p],l,mid,x); else update(rs[p],mid+1,r,x); } int query(int p,int l,int r,int x){ if(!p)return INF; if(l==r)return w(t[p],x); int mid=l+r>>1;int ret=w(t[p],x); if(x<=mid)ret=min(ret,query(ls[p],l,mid,x)); else ret=min(ret,query(rs[p],mid+1,r,x)); return ret; } int merge(int p,int q,int l,int r){ if(!p||!q)return p|q; update(p,l,r,t[q]); int mid=l+r>>1; ls[p]=merge(ls[p],ls[q],l,mid); rs[p]=merge(rs[p],rs[q],mid+1,r); return p; } void dfs(int u,int fa){ for(auto v:G[u]){ if(v==fa)continue;dfs(v,u); rt[u]=merge(rt[u],rt[v],1,MX); } f[u]=query(rt[u],1,MX,A[u]+DT); if(f[u]==INF)f[u]=0; k[u]=B[u];b[u]=f[u]-B[u]*DT; update(rt[u],1,MX,u); } signed main(){ scanf("%lld",&n); for(int i=1;i<=n;i++)scanf("%lld",&A[i]); for(int i=1;i<=n;i++)scanf("%lld",&B[i]); for(int i=1,u,v;i<n;i++){ scanf("%lld%lld",&u,&v); G[u].push_back(v); G[v].push_back(u); }dfs(1,0); for(int i=1;i<=n;i++)printf("%lld ",f[i]); return puts("")&0; }
有源汇上下界最大流
int work(int s,int t){ S=N-1,T=N-2; for(int i=1;i<=m;i++){ w[e[i].x]-=e[i].dn; w[e[i].y]+=e[i].dn; add(e[i].x,e[i].y,e[i].up-e[i].dn); } int sum=0; for(int i=1;i<=n;i++) if(w[i]>0)add(S,i,w[i]),sum+=w[i]; else if(w[i]<0)add(i,T,-w[i]); add(t,s,INF); int ret=dinic(); if(ret!=sum)return -1; int ans=edge[tot]; edge[tot]=edge[tot^1]=0; S=s;T=t; return ans+dinic(); }
有源汇上下界最小流
int work(int s,int t){ S=N-1,T=N-2; for(int i=1;i<=m;i++){ w[e[i].x]-=e[i].dn; w[e[i].y]+=e[i].dn; add(e[i].x,e[i].y,e[i].up-e[i].dn); } int sum=0; for(int i=1;i<=n;i++) if(w[i]>0)add(S,i,w[i]),sum+=w[i]; else if(w[i]<0)add(i,T,-w[i]); add(t,s,INF); int ret=dinic(); if(ret!=sum)return -1; int ans=edge[tot]; edge[tot]=edge[tot^1]=0; S=t;T=s; return ans-dinic(); }
珂朵莉树 https://codeforces.com/problemset/problem/896/C
#include<bits/stdc++.h> #define int long long using namespace std; const int MOD=1e9+7,N=1e5+5; int a[N]; int fpow(int a,int b,int P){ int ret=1;a%=P; for(;b;b>>=1){ if(b&1)ret=1LL*ret*a%P; a=1LL*a*a%P; }return ret; } struct Node{ int l,r; mutable int v; Node(){l=r=v=0;} Node(int L,int R,int V){l=L;r=R;v=V;} bool operator<(const Node &a)const{return l<a.l;} }; set<Node>s; set<Node>::iterator split(int pos){ set<Node>::iterator it=s.lower_bound(Node(pos,0,0)); if(it!=s.end()&&it->l==pos)return it; it--;if(it->r<pos)return s.end(); int l=it->l,r=it->r,v=it->v; s.erase(it);s.insert(Node(l,pos-1,v)); return s.insert(Node(pos,r,v)).first; } void assign(int l,int r,int x){ set<Node>::iterator itr=split(r+1),itl=split(l); s.erase(itl,itr); s.insert(Node(l,r,x)); } void add(int l,int r,int x){ set<Node>::iterator itr=split(r+1),itl=split(l); for(set<Node>::iterator it=itl;it!=itr;it++) it->v+=x; } struct Fuck{int x,y;}tmp[N]; bool cmp(Fuck a,Fuck b){return a.x<b.x;} int kth(int l,int r,int x){ set<Node>::iterator itr=split(r+1),itl=split(l); int tot=0; for(set<Node>::iterator it=itl;it!=itr;it++) tmp[++tot].x=it->v,tmp[tot].y=it->r-it->l+1; sort(tmp+1,tmp+tot+1,cmp); int k=0; for(int i=1;i<=tot;i++) if((k+=tmp[i].y)>=x)return tmp[i].x; } int ans(int l,int r,int x,int y){ set<Node>::iterator itr=split(r+1),itl=split(l); int ret=0; for(set<Node>::iterator it=itl;it!=itr;it++) ret=(ret+1LL*(it->r-it->l+1)%y*fpow(it->v,x,y)%y)%y; return ret; } int n,m,seed,vmax; int rnd(){ int ret=seed; seed=(seed*7+13)%MOD; return ret; } signed main(){ cin>>n>>m>>seed>>vmax; for(int i=1;i<=n;i++){ a[i]=rnd()%vmax+1; s.insert(Node(i,i,a[i])); } while(m--){ int op,l,r,x,y; op=(rnd()%4)+1; l=(rnd()%n)+1,r=(rnd()%n)+1; if(l>r)swap(l,r); if(op==3)x=rnd()%(r-l+1)+1; else x=rnd()%vmax+1; if(op==4)y=rnd()%vmax+1; if(op==1)add(l,r,x); else if(op==2)assign(l,r,x); else if(op==3)printf("%lld\n",kth(l,r,x)); else printf("%lld\n",ans(l,r,x,y)); } return 0; }
Min_25筛 https://www.luogu.com.cn/problem/P5325
#include<bits/stdc++.h> #define int long long using namespace std; const int mod=1e9+7,N=2e5+5; int iv2,iv6,T,n; int v[N],p[N],cnt; int id1[N],id2[N],sp1[N],sp2[N],g1[N],g2[N]; int w[N],tot; int fpow(int a,int b){ int ret=1; for(;b;b>>=1){ if(b&1)ret=ret*a%mod; a=a*a%mod; }return ret; } long long S(int x,int y){ if(p[y]>=x)return 0; int k=x<=T?id1[x]:id2[n/x]; int ans=(g2[k]-g1[k]-(sp2[y]-sp1[y]))%mod; for(int i=y+1;i<=cnt&&p[i]*p[i]<=x;i++){ int pe=p[i]; for(int e=1;pe<=x;e++,pe=pe*p[i]) (ans+=pe%mod*((pe%mod-1)%mod)%mod*(S(x/pe,i)+(e!=1))%mod)%=mod; }return ans; } signed main(){ iv2=fpow(2,mod-2);iv6=fpow(6,mod-2); cin>>n;T=sqrt(n); for(int i=2;i<=T;i++){ if(!v[i])v[i]=i,p[++cnt]=i; for(int j=1;j<=cnt;j++){ if(p[j]>v[i]||p[j]>T/i)break; v[i*p[j]]=p[j]; } } for(int i=1;i<=cnt;i++){ sp1[i]=(sp1[i-1]+p[i])%mod; sp2[i]=(sp2[i-1]+p[i]*p[i]%mod)%mod; } for(int l=1,r=0;l<=n;l=r+1){ r=n/(n/l);w[++tot]=n/l; g1[tot]=w[tot]%mod; g2[tot]=g1[tot]*(g1[tot]+1)%mod*(2*g1[tot]%mod+1)%mod*iv6%mod;(g2[tot]-=1)%=mod; g1[tot]=g1[tot]*(g1[tot]+1)%mod*iv2%mod;(g1[tot]-=1)%=mod; if(n/l<=T)id1[n/l]=tot; else id2[n/(n/l)]=tot; } for(int i=1;i<=cnt;i++) for(int j=1;j<=tot&&p[i]*p[i]<=w[j];j++){ int k=w[j]/p[i]<=T?id1[w[j]/p[i]]:id2[n/(w[j]/p[i])]; (g1[j]-=p[i]*(g1[k]-sp1[i-1])%mod)%=mod; (g2[j]-=p[i]*p[i]%mod*(g2[k]-sp2[i-1])%mod)%=mod; } cout<<((S(n,0)+1)+mod)%mod<<endl; return 0; }
杜教筛 https://www.luogu.com.cn/problem/P4213
#include<bits/stdc++.h> #define int long long using namespace std; const int N=1e6; int mu[N+5],phi[N+5]; int v[N+5],p[N+5],m; map<int,int>Ans1,Ans2; int sum1[N+5],sum2[N+5]; void prework(int n){ memset(v,m=0,sizeof(v)); phi[1]=mu[1]=1; for(int i=2;i<=n;i++){ if(v[i]==0){ v[i]=i,p[++m]=i; phi[i]=i-1;mu[i]=-1; } for(int j=1;j<=m;j++){ if(p[j]>v[i]||p[j]>n/i)break; v[i*p[j]]=p[j]; if(i%p[j])mu[i*p[j]]=-mu[i],phi[i*p[j]]=phi[i]*(p[j]-1); else {mu[i*p[j]]=0;phi[i*p[j]]=phi[i]*p[j];} } } sum1[0]=sum2[0]=0; // cout<<"NMSL "<<sum2[0]<<' '<<phi[1]<<endl; for(int i=1;i<=n;i++)sum1[i]=sum1[i-1]+mu[i]; for(int i=1;i<=n;i++){ sum2[i]=sum2[i-1]+phi[i]; // cout<<i<<" : "<<sum2[i]<<endl;system("pause"); } } int get_mu(int x){ if(x<=N)return sum1[x]; if(Ans1[x])return Ans1[x]; int ans=1; for(int l=2,r;l<=x;l=r+1){ r=x/(x/l); ans-=(r-l+1)*get_mu(x/l); } return Ans1[x]=ans; } int get_phi(int x){ if(x<=N)return sum2[x]; if(Ans2[x])return Ans2[x]; int ans=x*(x+1)>>1; for(int l=2,r;l<=x;l=r+1){ r=x/(x/l); ans-=(r-l+1)*get_phi(x/l); } return Ans2[x]=ans; } signed main(){ prework(N);int T; scanf("%lld",&T); while(T--){ int n;scanf("%lld",&n); printf("%lld %lld\n",get_phi(n),get_mu(n)); } return 0; }
Miller Rabin https://www.luogu.com.cn/problem/SP288
#include<bits/stdc++.h> using namespace std; #define int long long const int p[12]={2,3,5,7,11,13,17,19,23,29,31,37}; int fmul(int a,int b,int mod){ int ret=0; for(;b;b>>=1){ if(b&1)ret=(ret+a)%mod; a=a*2%mod; }return ret; } int fpow(int a,int b,int mod){ int ret=1; for(;b;b>>=1){ if(b&1)ret=fmul(ret,a,mod); a=fmul(a,a,mod); }return ret; } bool ck(int n,int m){ int sum=0,d=n-1; while(!(d&1))d>>=1,sum++; int z=fpow(m,d,n); if(!(z-1))return 1; for(int i=0;i<sum;i++){ if(z==n-1)return 1; z=fmul(z,z,n); }return 0; } bool Miller_Rabin(int n){ if(n<2)return 0; for(int i=0;i<12;i++){ if(p[i]==n)return 1; if(n%p[i]==0)return 0; if(!ck(n,p[i]))return 0; }return 1; } signed main(){ int T;cin>>T; while(T--){ int n;cin>>n; puts(Miller_Rabin(n)?"YES":"NO"); }return 0; }
Pollard Rho https://www.luogu.com.cn/problem/P4718
#include<bits/stdc++.h> using namespace std; #define int long long #define lll __int128 const int p[12]={2,3,5,7,11,13,17,19,23,29,31,37}; int ans; const int M=(1LL<<7)-1; int fmul(int a,int b,int mod){ int ret=0; for(;b;b>>=1){ if(b&1)ret=(ret+a)%mod; a=a*2%mod; }return ret; } int fpow(int a,int b,int mod){ int ret=1; for(;b;b>>=1){ if(b&1)ret=fmul(ret,a,mod); a=fmul(a,a,mod); }return ret; } bool ck(int n,int m){ int sum=0,d=n-1; while(!(d&1))d>>=1,sum++; int z=fpow(m,d,n); if(!(z-1))return 1; for(int i=0;i<sum;i++){ if(z==n-1)return 1; z=fmul(z,z,n); }return 0; } bool Miller_Rabin(int n){ if(n<2)return 0; for(int i=0;i<12;i++){ if(p[i]==n)return 1; if(n%p[i]==0)return 0; if(!ck(n,p[i]))return 0; }return 1; } int gcd(int a,int b){return b?gcd(b,a%b):a;} int G(int x,int n,int c){return ((lll)x*x+c)%n;} int rd(){return rand()*rand();} int Pollard_Rho(int n){ if(n%2==0)return 2; if(n%3==0)return 3; int pr=0,x=0,q=1,t=1,c=rd()%(n-1)+1; for(int k=1;;k<<=1,pr=x,q=1){ for(int i=1;i<=k;i++){ x=G(x,n,c),q=(lll)q*abs(x-pr)%n; if(!(i%M)){t=gcd(q,n);if(t>1)return t;} } if(t>1||(t=gcd(q,n))>1)return t; } } void find(int x){ if(x<=1||x<=ans)return; if(Miller_Rabin(x))return ans=max(ans,x),void(); int p=x; while(p>=x)p=Pollard_Rho(x); while(x%p==0)x/=p; find(x);find(p); } signed main(){ srand(time(0)); int T;cin>>T; double st=clock(); while(T--){ int n;ans=0;cin>>n;find(n); if(ans==n)puts("Prime"); else cout<<ans<<endl; } return 0; }

浙公网安备 33010602011771号