模板
图论:
最小生成树
kruskal
#include<cmath> #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define ll long long const int maxn=5000+50; const int maxm=200000+50; int n,m,fat[maxn]; struct node{int x,y,z;}a[maxm]; int cmp(const node &a,const node &b){return a.z<b.z;} int father(int x){ if(x!=fat[x]) fat[x]=father(fat[x]); return fat[x]; } void kruskal(){ int k=0,ans=0; for(int i=1;i<=m;i++){ int fa=father(a[i].x); int fb=father(a[i].y); if(fa!=fb){ fat[fa]=fb; k++; ans+=a[i].z; } if(k==n-1) break; } if(k==n-1) printf("%d",ans); else printf("orz"); } template<typename T>void read(T& aa){ char cc; ll ff;aa=0;cc=getchar();ff=1; while((cc<'0'||cc>'9')&&cc!='-') cc=getchar(); if(cc=='-') ff=-1,cc=getchar(); while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar(); aa*=ff; } int main(){ read(n),read(m); for(int i=1;i<=n;i++) fat[i]=i; for(int i=1;i<=m;i++) read(a[i].x),read(a[i].y),read(a[i].z); sort(a+1,a+1+m,cmp); kruskal(); return 0; }
kruskal重构树
#include<cmath> #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define ll long long const int maxn=200000+50; int n,m,k,aa,bb,fat[maxn],cnt; int fir[maxn],to[maxn],nex[maxn],ecnt; int son[maxn],dep[maxn],sz[maxn],fa[maxn],top[maxn],val[maxn]; struct node{int x,y,z;}a[maxn]; void add_edge(int u,int v){ nex[++ecnt]=fir[u];fir[u]=ecnt;to[ecnt]=v; } int cmp(const node &a,const node &b){ return a.z<b.z; } int father(int x){ if(x!=fat[x]) fat[x]=father(fat[x]); return fat[x]; } void dfs1(int x,int f,int deep){ dep[x]=deep; fa[x]=f; sz[x]=1; int maxson=-1; for(int e=fir[x];e;e=nex[e]){ int v=to[e]; if(v==f) continue; dfs1(v,x,deep+1); sz[x]+=sz[v]; if(sz[v]>maxson) maxson=sz[v],son[x]=v; } } void dfs2(int x,int topf){ top[x]=topf; if(!son[x]) return ; dfs2(son[x],topf); for(int e=fir[x];e;e=nex[e]){ int v=to[e]; if(v==fa[x]||v==son[x]) continue; dfs2(v,v); } } template<typename T>void read(T& aa){ char cc; ll ff;aa=0;cc=getchar();ff=1; while((cc<'0'||cc>'9')&&cc!='-') cc=getchar(); if(cc=='-') ff=-1,cc=getchar(); while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar(); aa*=ff; } void kruskal(){ sort(a+1,a+1+m,cmp); for(int i=1;i<=m;i++){ if(father(a[i].x)!=father(a[i].y)){ int fa=father(a[i].x),fb=father(a[i].y); val[++cnt]=a[i].z; fat[cnt]=fat[fa]=fat[fb]=cnt; add_edge(fa,cnt); add_edge(cnt,fa); add_edge(fb,cnt); add_edge(cnt,fb); } } } int lca(int x,int y){ int f1=top[x],f2=top[y]; while(f1!=f2){ if(dep[f1]<dep[f2]) swap(f1,f2),swap(x,y); x=fa[f1];f1=top[x]; } return dep[x]<dep[y]?x:y; } int main(){ read(n),read(m),read(k);cnt=n; for(int i=1;i<=m;i++) read(a[i].x),read(a[i].y),read(a[i].z); for(int i=1;i<=n;i++) fat[i]=i; kruskal(); dfs1(cnt,0,1);dfs2(cnt,cnt); while(k--){ read(aa),read(bb); cout<<val[lca(aa,bb)]<<endl; } return 0; }
最短路
floyed
void floyd(){ memset(dis,63,sizeof(dis)); for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]); }
spfa
#include<queue> #include<cmath> #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define ll long long const int maxn=10000+50; const int maxm=500000+50; const int inf=2147483647; int n,m,s,d[maxn]; int fir[maxn],nex[maxm],to[maxm],wi[maxm],ecnt; bool vis[maxn]; queue<int> q; void add(int u,int v,int w){ nex[++ecnt]=fir[u];fir[u]=ecnt;to[ecnt]=v;wi[ecnt]=w; } void spfa(int x){ memset(vis,false,sizeof(vis));vis[x]=true; for(int i=1;i<=n;i++) d[i]=inf;d[x]=0; q.push(x); while(!q.empty()){ int u=q.front();q.pop(); vis[u]=false; for(int e=fir[u];e;e=nex[e]){ int v=to[e]; if(d[v]>d[u]+wi[e]){ d[v]=d[u]+wi[e]; if(!vis[v]){ q.push(v); vis[v]=true; } } } } } template<typename T>void read(T& aa){ char cc; ll ff;aa=0;cc=getchar();ff=1; while((cc<'0'||cc>'9')&&cc!='-') cc=getchar(); if(cc=='-') ff=-1,cc=getchar(); while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar(); aa*=ff; } int main(){ read(n),read(m),read(s); for(int i=1;i<=m;i++){ int x,y,z; read(x),read(y),read(z); add(x,y,z); } spfa(s); for(int i=1;i<=n;i++) printf("%d ",d[i]); return 0; }
dijsktra
#include<queue> #include<cmath> #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define ll long long const int maxn=100000+50; const int maxm=200000+50; int n,m,s,d[maxn]; int fir[maxn],nex[maxm],to[maxm],wi[maxm],ecnt; bool vis[maxn]; priority_queue<pair<ll,int> > q; void add(int u,int v,int w){ nex[++ecnt]=fir[u];fir[u]=ecnt;to[ecnt]=v;wi[ecnt]=w; } void dijsktra(int x){ memset(vis,false,sizeof(vis)); memset(d,127,sizeof(d));d[x]=0; q.push(make_pair(0,x)); while(!q.empty()){ int u=q.top().second;q.pop(); if(vis[u]) continue; vis[u]=true; for(int e=fir[u];e;e=nex[e]){ int v=to[e]; if(d[v]>d[u]+wi[e]){ d[v]=d[u]+wi[e]; q.push(make_pair(-d[v],v)); } } } } template<typename T>void read(T& aa){ char cc; ll ff;aa=0;cc=getchar();ff=1; while((cc<'0'||cc>'9')&&cc!='-') cc=getchar(); if(cc=='-') ff=-1,cc=getchar(); while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar(); aa*=ff; } int main(){ read(n),read(m),read(s); for(int i=1;i<=m;i++){ int x,y,z; read(x),read(y),read(z); add(x,y,z); } dijsktra(s); for(int i=1;i<=n;i++) printf("%d ",d[i]); return 0; }
tarjan
强连通分量
#include<cmath> #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define ll long long const int maxn=10000+50; const int maxm=50000+50; int fir[maxn],nex[maxm],to[maxm],ecnt; int col[maxn],dfn[maxm],low[maxm],stack[maxm],vis[maxn],cnt[maxn]; int n,m,t,deep,sum,ans,x,y; void add_edge(int u,int v){ nex[++ecnt]=fir[u];fir[u]=ecnt;to[ecnt]=v; } template<typename T>void read(T& aa){ char cc; ll ff;aa=0;cc=getchar();ff=1; while((cc<'0'||cc>'9')&&cc!='-') cc=getchar(); if(cc=='-') ff=-1,cc=getchar(); while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar(); aa*=ff; } int tarjan(int u){ dfn[u]=++deep; low[u]=deep; vis[u]=1; stack[++t]=u; for(int e=fir[u];e;e=nex[e]){ int v=to[e]; 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]){ col[u]=++sum; vis[u]=0; while(stack[t]!=u){ col[stack[t]]=sum; vis[stack[t--]]=0; } t--; } } int main(){ read(n),read(m); for(int i=1;i<=m;i++){ read(x),read(y); add_edge(x,y); } for(int i=1;i<=n;i++){ if(!dfn[i]) tarjan(i); } for(int i=1;i<=n;i++) cnt[col[i]]++; for(int i=1;i<=sum;i++){ if(cnt[i]>1) ans++; } cout<<ans<<endl; return 0; }
最近公共祖先
倍增
#include<cmath> #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define ll long long const int maxn=500000+5; const int maxm=500000*2+5; int n,m,s,x,y,a,b; int fir[maxn],to[maxm],nex[maxm],ecnt; int anc[maxn][22],lg[maxn],dep[maxn]; void add_edge(int u,int v){ nex[++ecnt]=fir[u];fir[u]=ecnt;to[ecnt]=v; } template<typename T>void read(T& aa){ char cc; ll ff;aa=0;cc=getchar();ff=1; while((cc<'0'||cc>'9')&&cc!='-') cc=getchar(); if(cc=='-') ff=-1,cc=getchar(); while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar(); aa*=ff; } void dfs(int u,int fa){ dep[u]=dep[fa]+1;anc[u][0]=fa; for(int i=1;(1<<i)<=dep[u];i++) anc[u][i]=anc[anc[u][i-1]][i-1]; for(int e=fir[u];e;e=nex[e]) if(to[e]!=fa) dfs(to[e],u); } int lca(int x,int y){ if(dep[x]<dep[y]) swap(x,y); while(dep[x]>dep[y]) x=anc[x][lg[dep[x]-dep[y]]-1]; if(x==y) return x; for(int k=lg[dep[x]];k>=0;k--) if(anc[x][k]!=anc[y][k]) x=anc[x][k],y=anc[y][k]; return anc[x][0]; } int main(){ read(n),read(m),read(s); for(int i=1;i<n;i++){ read(x),read(y); add_edge(x,y);add_edge(y,x); } dfs(s,0); for(int i=1;i<=n;i++) lg[i]=lg[i-1]+(1<<lg[i-1]==i); for(int i=1;i<=m;i++){ read(a),read(b); printf("%d\n",lca(a,b)); } return 0; }
树剖
#include<cmath> #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define ll long long const int maxn=500000+50; const int maxm=500000*2+50; int n,m,s; int fir[maxn],nex[maxm],to[maxm],ecnt; int fa[maxn],top[maxm],sz[maxn],son[maxn],dep[maxn]; void add(int u,int v){ nex[++ecnt]=fir[u];fir[u]=ecnt;to[ecnt]=v; } void dfs1(int x,int f,int deep){ fa[x]=f; dep[x]=deep; sz[x]=1; for(int e=fir[x];e;e=nex[e]){ int v=to[e]; if(v==f) continue; dfs1(v,x,deep+1); sz[x]+=sz[v]; if(sz[v]>sz[son[x]]) son[x]=v; } } void dfs2(int x,int topf){ top[x]=topf; if(!son[x]) return ; dfs2(son[x],topf); for(int e=fir[x];e;e=nex[e]){ int v=to[e]; if(v==fa[x]||v==son[x]) continue; dfs2(v,v); } } int lca(int x,int y){ int f1=top[x],f2=top[y]; while(f1!=f2){ if(dep[f1]<dep[f2]) swap(x,y),swap(f1,f2); x=fa[f1];f1=top[x]; } return dep[x]<dep[y]?x:y; } template<typename T>void read(T& aa){ char cc; ll ff;aa=0;cc=getchar();ff=1; while((cc<'0'||cc>'9')&&cc!='-') cc=getchar(); if(cc=='-') ff=-1,cc=getchar(); while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar(); aa*=ff; } int main(){ read(n),read(m),read(s); for(int i=1;i<n;i++){ int x,y; read(x),read(y); add(x,y);add(y,x); } dfs1(s,0,1); dfs2(s,s); while(m--){ int x,y; read(x),read(y); printf("%d\n",lca(x,y)); } return 0; }
树链剖分
#include<cmath> #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define ll long long const int maxn=1e5+50; const int maxm=2e5+50; int n,m,r,p,val[maxn],cnt; int fir[maxn],nex[maxm],to[maxm],ecnt; int son[maxn],dep[maxn],sz[maxn],top[maxn],fa[maxn],id[maxn],wt[maxn]; struct SegmentTree{int l,r;ll v,add;}st[maxn<<2]; void add(int u,int v){ nex[++ecnt]=fir[u];fir[u]=ecnt;to[ecnt]=v; } void dfs1(int x,int f,int deep){ fa[x]=f;dep[x]=deep; sz[x]=1; for(int e=fir[x];e;e=nex[e]){ int v=to[e]; if(v==f) continue; dfs1(v,x,deep+1); sz[x]+=sz[v]; if(sz[v]>sz[son[x]]) son[x]=v; } } void dfs2(int x,int topf){ top[x]=topf; id[x]=++cnt; wt[cnt]=val[x]; if(!son[x]) return ; dfs2(son[x],topf); for(int e=fir[x];e;e=nex[e]){ int v=to[e]; if(v==fa[x]||v==son[x]) continue; dfs2(v,v); } } void pushup(int root){ st[root].v=(st[root<<1].v+st[root<<1|1].v)%p; } void build(int root,int l,int r){ st[root].l=l;st[root].r=r; if(l==r) st[root].v=wt[l]; else{ int m=l+r>>1; build(root<<1,l,m);build(root<<1|1,m+1,r); pushup(root); } } void pushdown(int root){ st[root<<1].v=(st[root<<1].v+st[root].add*(st[root<<1].r-st[root<<1].l+1))%p; st[root<<1|1].v=(st[root<<1|1].v+st[root].add*(st[root<<1|1].r-st[root<<1|1].l+1))%p; st[root<<1].add=(st[root<<1].add+st[root].add)%p; st[root<<1|1].add=(st[root<<1|1].add+st[root].add)%p; st[root].add=0; } void change(int root,int l,int r,ll val){ if(st[root].l>r||st[root].r<l) return ; if(st[root].l>=l&&st[root].r<=r){ st[root].v=(st[root].v+val*(st[root].r-st[root].l+1))%p; st[root].add=(st[root].add+val)%p; } else{ pushdown(root); change(root<<1,l,r,val);change(root<<1|1,l,r,val); pushup(root); } } ll query(int root,int l,int r){ if(st[root].l>r||st[root].r<l) return 0; if(st[root].l>=l&&st[root].r<=r) return st[root].v; pushdown(root); return (query(root<<1,l,r)+query(root<<1|1,l,r))%p; } void Chg(int x,int y,ll val){ int f1=top[x],f2=top[y]; while(f1!=f2){ if(dep[f1]<dep[f2]) swap(f1,f2),swap(x,y); change(1,id[f1],id[x],val); x=fa[f1];f1=top[x]; } if(dep[x]>dep[y]) swap(x,y); change(1,id[x],id[y],val); } ll Qry(int x,int y){ int f1=top[x],f2=top[y];ll ans=0; while(f1!=f2){ if(dep[f1]<dep[f2]) swap(f1,f2),swap(x,y); ans=(ans+query(1,id[f1],id[x])); x=fa[f1];f1=top[x]; } if(dep[x]>dep[y]) swap(x,y); ans=(ans+query(1,id[x],id[y]))%p; return ans; } template<typename T>void read(T& aa){ char cc; ll ff;aa=0;cc=getchar();ff=1; while((cc<'0'||cc>'9')&&cc!='-') cc=getchar(); if(cc=='-') ff=-1,cc=getchar(); while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar(); aa*=ff; } int main(){ read(n),read(m),read(r),read(p); for(int i=1;i<=n;i++) read(val[i]); for(int i=1;i<n;i++){ int x,y; read(x),read(y); add(x,y);add(y,x); } dfs1(r,0,1);dfs2(r,r);build(1,1,n); while(m--){ int op,x,y,z; read(op); if(op==1){ read(x),read(y),read(z); Chg(x,y,z); } else if(op==2){ read(x),read(y); printf("%lld\n",Qry(x,y)); } else if(op==3){ read(x),read(y); change(1,id[x],id[x]+sz[x]-1,y); } else{ read(x); printf("%lld\n",query(1,id[x],id[x]+sz[x]-1)); } } return 0; }
数据结构:
树状数组
单点加,区间和
#include<cmath> #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define ll long long const int maxn=500000+5; int a[maxn],c[maxn],n,m,op,x,y,k; template<typename T>void read(T& aa) { char cc; ll ff;aa=0;cc=getchar();ff=1; while((cc<'0'||cc>'9')&&cc!='-') cc=getchar(); if(cc=='-') ff=-1,cc=getchar(); while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar(); aa*=ff; } int lowbit(int x){return x&(-x);} int query(int x){ int ans=0; while(x){ ans+=c[x];x-=lowbit(x); } return ans; } void update(int x,int y){ while(x<=n){ c[x]+=y;x+=lowbit(x); } } int main(){ read(n),read(m); for(int i=1;i<=n;i++){ read(a[i]); update(i,a[i]); } while(m--){ read(op); if(op==1){ read(x),read(y); update(x,y); } else { read(x),read(y); printf("%d\n",query(y)-query(x-1)); } } return 0; }
区间加,单点查询
#include<cmath> #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define ll long long const int maxn=500000+5; int a[maxn],c[maxn],n,m,x,y,k,op,now; template<typename T>void read(T& aa) { char cc; ll ff;aa=0;cc=getchar();ff=1; while((cc<'0'||cc>'9')&&cc!='-') cc=getchar(); if(cc=='-') ff=-1,cc=getchar(); while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar(); aa*=ff; } int lowbit(int x){return x&(-x);} int query(int x){ int ans=0; while(x){ ans+=c[x];x-=lowbit(x); } return ans; } void update(int x,int y){ while(x<=n){ c[x]+=y;x+=lowbit(x); } } int main(){ read(n),read(m); for(int i=1;i<=n;i++){ read(a[i]); update(i,a[i]-now); now=a[i]; } while(m--){ read(op); if(op==1){ read(x),read(y),read(k); update(x,k);update(y+1,-k); } else{ read(x); printf("%d\n",query(x)); } } return 0; }
线段树
#include<cmath> #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define ll long long const int maxn=100000+50; int n,m,p;ll a[maxn]; struct SegmentTree{int l,r;ll v,add,mul;}st[maxn<<2]; void pushup(int root){ st[root].v=(st[root<<1].v+st[root<<1|1].v)%p; } void build(int root,int l,int r){ st[root].l=l;st[root].r=r;st[root].mul=1; if(l==r) st[root].v=a[l]; else{ int m=l+r>>1; build(root<<1,l,m);build(root<<1|1,m+1,r); pushup(root); } } void pushdown(int root){ st[root<<1].v=(st[root<<1].v*st[root].mul+st[root].add*(st[root<<1].r-st[root].l+1))%p; st[root<<1|1].v=(st[root<<1|1].v*st[root].mul+st[root].add*(st[root<<1|1].r-st[root<<1|1].l+1))%p; st[root<<1].mul=st[root<<1].mul*st[root].mul%p; st[root<<1|1].mul=st[root<<1|1].mul*st[root].mul%p; st[root<<1].add=(st[root<<1].add*st[root].mul+st[root].add)%p; st[root<<1|1].add=(st[root<<1|1].add*st[root].mul+st[root].add)%p; st[root].add=0;st[root].mul=1; } void u1(int root,int l,int r,ll val){ if(st[root].l>r||st[root].r<l) return ; if(st[root].l>=l&&st[root].r<=r){ st[root].v=st[root].v*val%p; st[root].add=st[root].add*val%p; st[root].mul=st[root].mul*val%p; } else{ pushdown(root); u1(root<<1,l,r,val);u1(root<<1|1,l,r,val); pushup(root); } } void u2(int root,int l,int r,ll val){ if(st[root].l>r||st[root].r<l) return ; if(st[root].l>=l&&st[root].r<=r){ st[root].v=(st[root].v+val*(st[root].r-st[root].l+1))%p; st[root].add=(st[root].add+val)%p; } else{ pushdown(root); u2(root<<1,l,r,val);u2(root<<1|1,l,r,val); pushup(root); } } ll query(int root,int l,int r){ if(st[root].l>r||st[root].r<l) return 0; if(st[root].l>=l&&st[root].r<=r) return st[root].v; pushdown(root); return (query(root<<1,l,r)+query(root<<1|1,l,r))%p; } template<typename T>void read(T& aa){ char cc; ll ff;aa=0;cc=getchar();ff=1; while((cc<'0'||cc>'9')&&cc!='-') cc=getchar(); if(cc=='-') ff=-1,cc=getchar(); while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar(); aa*=ff; } int main(){ read(n),read(m),read(p); for(int i=1;i<=n;i++) read(a[i]); build(1,1,n); while(m--){ int op,x,y;ll k; read(op),read(x),read(y); if(op==1){ read(k); u1(1,x,y,k); } else if(op==2){ read(k); u2(1,x,y,k); } else printf("%lld\n",query(1,x,y)); } return 0; }
权值线段树
#include<cmath> #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #define ll long long #define ull unsigned long long #define maxx 2139062143 #define maxint 2147483647 using namespace std; const int maxn=100000+5; int T[4*maxn]; int n,opt[maxn],a[maxn],ma[maxn],e,x; struct Data{ int v,p; }t[maxn]; bool cmp(const Data &a,const Data &b){ return a.v<b.v; } int read(){ int xx=0,kk=1;char ch; while(ch<'0'||ch>'9') {if(ch=='-')kk=-1;ch=getchar();} while(ch>='0'&&ch<='9'){xx=xx*10+ch-'0';ch=getchar();} return kk*xx; } void update(int root,int p,int v,int l,int r){//插入p时v==1,删除p时v==-1 T[root]+=v; if(l==r) return ; int m=(l+r>>1); if(p<=m) update(root*2,p,v,l,m); else update(root*2+1,p,v,m+1,r); } int kth(int root,int k,int l,int r){ if(l==r) return l; int m=(l+r>>1); if(T[root*2]>=k) return kth(root*2,k,l,m); return kth(root*2+1,k-T[root*2],m+1,r); } int rank(int root,int p,int l,int r){ if(r<p) return T[root]; int m=(l+r>>1),res=0; res+=rank(root*2,p,l,m); if(m<p-1) res+=rank(root*2+1,p,m+1,r); return res; } int findp(int root,int l,int r){ if(l==r) return l; int m=(l+r>>1); if(T[root*2+1]) return findp(root*2+1,m+1,r); return findp(root*2,l,m); } int pre(int root,int p,int l,int r){ if(r<p){ if(T[root]) return findp(root,l,r); return 0; } int m=(l+r)>>1,re; if(m<p-1&&T[root*2+1]&&(re=pre(root*2+1,p,m+1,r))) return re; return pre(root*2,p,l,m); } int findn(int root,int l,int r){ if(l==r) return l; int m=(l+r)>>1; if(T[root*2]) return findn(root*2,l,m); return findn(root*2+1,m+1,r); } int nex(int root,int p,int l,int r){ if(p<l){ if(T[root]) return findn(root,l,r); return 0; } int m=(l+r)>>1,re; if(p<m&&T[root*2]&&(re=nex(root*2,p,l,m))) return re; return nex(root*2+1,p,m+1,r); } int main(){ scanf("%d",&n); for(int i=1;i<=n;++i){ scanf("%d%d",&opt[i],&t[i].v); t[i].p=i; } sort(t+1,t+1+n,cmp); a[t[1].p]=++e; ma[a[t[1].p]]=t[1].v; for(int i=2;i<=n;i++){ if(t[i].v!=t[i-1].v) ++e; a[t[i].p]=e; ma[a[t[i].p]]=t[i].v; } for(int i=1;i<=n;i++){ if(opt[i]==1) update(1,a[i],1,1,e); else if(opt[i]==2) update(1,a[i],-1,1,e); else if(opt[i]==3) printf("%d\n",rank(1,a[i],1,e)+1); else if(opt[i]==4) printf("%d\n",ma[kth(1,ma[a[i]],1,e)]); else if(opt[i]==5) printf("%d\n",ma[pre(1,a[i],1,e)]); else printf("%d\n",ma[nex(1,a[i],1,e)]); } return 0; }
RMQ
#include<cmath> #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define ll long long const int maxn=1e5+50; int n,m,ma[maxn][26]; struct RMQ{ int log2[maxn]; void init(){ for(int i=0;i<=n;i++) log2[i]=(i==0?-1:log2[i>>1]+1); for(int j=1;j<=20;j++) for(int i=1;i+(1<<j)-1<=n;i++) ma[i][j]=max(ma[i][j-1],ma[i+(1<<j-1)][j-1]); } int query(int ql,int qr){ int k=log2[qr-ql+1]; return max(ma[ql][k],ma[qr-(1<<k)+1][k]); } }rmq; template<typename T>void read(T& aa){ char cc; ll ff;aa=0;cc=getchar();ff=1; while((cc<'0'||cc>'9')&&cc!='-') cc=getchar(); if(cc=='-') ff=-1,cc=getchar(); while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar(); aa*=ff; } int main(){ read(n),read(m); for(int i=1;i<=n;i++) read(ma[i][0]); rmq.init(); while(m--){ int x,y; read(x),read(y); printf("%d\n",rmq.query(x,y)); } return 0; }
分块
#include<cmath> #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define ll long long const int maxn=500000+50; const int maxblo=1000; int bl[maxn],blo,n,a[maxn],m,sum[maxblo],tag[maxblo]; template<typename T>void read(T& aa){ char cc; ll ff;aa=0;cc=getchar();ff=1; while((cc<'0'||cc>'9')&&cc!='-') cc=getchar(); if(cc=='-') ff=-1,cc=getchar(); while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar(); aa*=ff; } int main(){ read(n);read(m); blo=sqrt(n); for(int i=1;i<=n;i++){ read(a[i]); bl[i]=(i-1)/blo+1; sum[bl[i]]+=a[i]; } while(m--){ int op,x,y; read(op),read(x),read(y); if(op==1){ a[x]+=y; sum[bl[x]]+=y; } else{ int ans=0; for(int i=bl[x]+1;i<=bl[y]-1;i++) ans+=sum[i]; for(int i=x;i<=bl[x]*blo;i++) ans+=a[i]; for(int i=(bl[y]-1)*blo+1;i<=y;i++) ans+=a[i]; printf("%d\n",ans); } } return 0; }
并查集
#include<cmath> #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define ll long long const int maxn=10000+50; const int maxm=200000+50; int n,m,fat[maxn]; int father(int x){ if(x!=fat[x]) fat[x]=father(fat[x]); return fat[x]; } template<typename T>void read(T& aa){ char cc; ll ff;aa=0;cc=getchar();ff=1; while((cc<'0'||cc>'9')&&cc!='-') cc=getchar(); if(cc=='-') ff=-1,cc=getchar(); while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar(); aa*=ff; } int main(){ read(n),read(m); for(int i=1;i<=n;i++) fat[i]=i; while(m--){ int x,y,op; read(op),read(x),read(y); int fa=father(x),fb=father(y); if(op==1){ fat[fa]=fb; } else{ if(fa==fb) cout<<"Y"<<endl; else cout<<"N"<<endl; } } return 0; }
数学:
gcd / lcm
int gcd(int a,int b){ int c; while(a%b){ c=a%b; a=b; b=c; } return b; }
int lcm(int a,int b){ return a*b/gcd(a,b); }
快速幂
#include<cmath> #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define ll long long int b,p,mod; ll qsm(ll a,ll n){ a%=mod;ll ans=1; for(ll i=n;i;i>>=1,a=(a*a)%mod) if(i&1) ans=(ans*a)%mod; return ans%mod; } template<typename T>void read(T& aa){ char cc; ll ff;aa=0;cc=getchar();ff=1; while((cc<'0'||cc>'9')&&cc!='-') cc=getchar(); if(cc=='-') ff=-1,cc=getchar(); while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar(); aa*=ff; } int main(){ read(b),read(p),read(mod); cout<<b<<"^"<<p<<" mod "<<mod<<"="<<qsm(b,p)<<endl; return 0; }
快速乘
O(logn)
ll qsc(ll a,ll b,ll c){ ll ans=0; a=a%c; b=b%c; while(b>0){ if(b&1) ans=(ans+a)%c; a=(a+a)%c; b>>=1; } return ans; }
O(1)
ll qsc(ll A,ll B,ll mod){ return (A*B-(ll)((long double)A*B/mod)*mod+mod)%mod; }
中国剩余定理
void exgcd(ll a,ll b,ll &d,ll &x,ll &y){ if(!b){ d=a;x=1;y=0; } else exgcd(b,a%b,d,y,x),y-=x*(a/b); } ll china(int n,int *a,int *m){ // x ≡ a[ i ] ( mod m[ i ] ) ll M=1,d,y,x=0; for(int i=1;i<=n;i++) M*=m[i]; for(int i=1;i<=n;i++){ ll w=M/m[i]; exgcd(m[i],w,d,d,y); x=(x+y*w*a[i])%M; } return (x+M)%M; }
线性筛素数
#include<cmath> #include<cstdio> #include<cstdlib> #include<iostream> #include<cstring> #include<algorithm> using namespace std; #define ll long long int n,q,k; bool isprime[100000010]; int prime[6000010],cnt=0; void Get(int n){ memset(isprime,true,sizeof(isprime)); isprime[1]=false; for(int i=2;i<=n;i++){ if(isprime[i]) prime[++cnt]=i; for(int j=1;j<=cnt&&i*prime[j]<=n;j++){ isprime[i*prime[j]]=false; if(i%prime[j]==0) break; } } } template<typename T>void inline read(T &aa){ ll ff=1;char cc=getchar();aa=0; while((cc<'0'||cc>'9')&&cc!='-') cc=getchar(); if(cc=='-') ff=-1,cc=getchar(); while(cc<='9'&&cc>='0') aa=aa*10+cc-48,cc=getchar(); aa*=ff; } int main(){ cin>>n>>q; Get(n); while(q--){ read(k); printf("%d\n",prime[k]); } return 0; }
根号n判素数
bool pd(int x){ if(x==0||x==1) return false; for(int i=2;i*i<=x;i++) if(x%i==0) return false; return true; }
bool pd(int x){ if(x==0||x==1||x==4) return false; if(x==2||x==3) return true; if(x%6!=1&&x%6!=5) return false; if(x%2==0||x%3==0) return false; for(int i=5;i*i<=x;i+=6) if(x%i==0||x%(i+2)==0) return false; return true; }
线性筛欧拉函数
void sphi(int limit){ phi[1]=1; for(int i=2;i<=limit;i++){ if(!a[i]) prime[++tot]=i,phi[i]=i-1; for(int j=1;j<=tot&&i*prime[j]<=limit;j++){ a[i*prime[j]]=1; if(i%prime[j]==0){ phi[i*prime[j]]=phi[i]*prime[j]; break; } else phi[i*prime[j]]=phi[i]*(prime[j]-1); } } }
根号n求欧拉函数
ll PHI(ll x){ ll ret=x; for(ll i=2;i*i<=x;i++) if(x%i==0){ ret=ret-ret/i; while(x%i==0) x/=i; } if(x>1) ret=ret-ret/x; return ret; }
基础算法
归并排序
#include<bits/stdc++.h> using namespace std; #define ll long long const int maxn=5e5+50; int c[maxn],d[maxn],n;ll ans; void merge_sort(int l,int r){ if(l==r) return ; int mid=l+r>>1,i,j,k; merge_sort(l,mid);merge_sort(mid+1,r); i=k=l;j=mid+1; while(i<=mid&&j<=r){ if(c[i]<=c[j]) d[k++]=c[i++]; else ans+=mid-i+1,d[k++]=c[j++]; } while(i<=mid) d[k++]=c[i++]; while(j<=r) d[k++]=c[j++]; for(int i=l;i<=r;i++) c[i]=d[i]; } int main(){ cin>>n; for(int i=1;i<=n;i++) cin>>c[i]; merge_sort(1,n); cout<<ans; return 0; }