模板合集
神奇的模板...总之各种各样的模板整理...已经准备用我现在的码风重新打一遍了...
高精度
- 已重载运算符.没写FFT什么的...
#include<cstdio> #include<cmath> #include<vector> #include<algorithm> #include<iostream> using namespace std; typedef long long LL; const int B = 10; const int W = 1; struct Big{ vector<int> s; void clear(){ s.clear(); } Big(LL num=0){ *this=num; } Big operator = (LL x){ clear(); do{ s.push_back(x%B),x/=B; }while(x); return *this; } Big operator = (const string &str){ clear(); int x,len=(str.length()-1)/W+1,l=str.length(); for(int i=0;i<len;i++){ int tt=l-i*W,st=max(0,tt-W); sscanf(str.substr(st,tt-st).c_str(),"%d",&x); s.push_back(x); }return *this; } }; istream& operator >> (istream & in,Big &a){ string s; if(!(in>>s)) return in; a=s;return in; } ostream& operator << (ostream &out,const Big &a){ cout<<a.s.back(); for(int i=a.s.size()-2;~i;i--){ cout.width(W),cout.fill('0'),cout<<a.s[i]; }return out; } bool operator < (const Big &a,const Big &b){ int la=a.s.size(),lb=b.s.size(); if(la<lb) return 1;if(la>lb) return 0; for(int i=la-1;~i;i--){ if(a.s[i]<b.s[i]) return 1; if(a.s[i]>b.s[i]) return 0; }return 0; } bool operator <= (const Big &a,const Big &b){ return !(b<a); } bool operator > (const Big &a,const Big &b){ return b<a; } bool operator >= (const Big &a,const Big &b){ return !(a<b); } bool operator == (const Big &a,const Big &b){ return !(a>b) && !(a<b); } bool operator != (const Big &a,const Big &b){ return a>b || a<b ; } Big operator + (const Big &a,const Big &b){ Big c;c.clear(); int lim=max(a.s.size(),b.s.size()),la=a.s.size(),lb=b.s.size(),i,g,x; for(i=0,g=0;;i++){ if(g==0 && i>=lim) break; x=g;if(i<la) x+=a.s[i];if(i<lb) x+=b.s[i]; c.s.push_back(x%B),g=x/B; }i=c.s.size()-1; while(c.s[i]==0 && i) c.s.pop_back(),i--; return c; } Big operator - (const Big &a,const Big &b){ Big c;c.clear(); int i,g,x,la=a.s.size(),lb=b.s.size(); for(i=0,g=0;i<la;i++){ x=a.s[i]-g; if(i<lb) x-=b.s[i]; if(x>=0) g=0;else g=1,x+=B; c.s.push_back(x); }i=c.s.size()-1; while(c.s[i]==0 && i) c.s.pop_back(),i--; return c; } Big operator * (const Big &a,const Big &b){ Big c; int i,j,la=a.s.size(),lb=b.s.size(),lc=la+lb; c.s.resize(lc,0); for(i=0;i<la;i++) for(j=0;j<lb;j++) c.s[i+j]+=a.s[i]*b.s[j]; for(i=0;i<lc;i++) c.s[i+1]+=c.s[i]/B,c.s[i]%=B; i=lc-1;while(c.s[i]==0 && i) c.s.pop_back(),i--; return c; } Big operator / (const Big &a,const Big &b){ Big c,f=0; int la=a.s.size(),i; c.s.resize(la,0); for(i=la-1;~i;i--){ f=f*B,f.s[0]=a.s[i]; int l=0,r=B,mid; while(l<=r){ mid=(l+r)>>1; if(mid*b > f) r=mid-1; else l=mid+1; } f=f-r*b,c.s[i]=r; // while(f>=b) f=f-b,c.s[i]++; }i=la-1;while(c.s[i]==0 && i) c.s.pop_back(),i--; return c; } Big operator % (const Big &a,const Big &b){ Big c=a-(a/b)*b; return c; } Big operator ^ (Big &a,Big &b){ Big c=1; for(;b!=0;b=b/2,a=a*a){ if(b.s[0] & 1) c=c*a; }return c; } Big operator += (Big &a,const Big &b){ return a=a+b; } Big operator -= (Big &a,const Big &b){ return a=a-b; } Big operator *= (Big &a,const Big &b){ return a=a*b; } Big operator /= (Big &a,const Big &b){ return a=a/b; } Big operator %= (Big &a,const Big &b){ return a=a%b; } int main(){ Big A,B; cin>>A>>B; cout<<A/B; return 0; }
- FFT \(O(nlogn)\)
#include <bits/stdc++.h> using namespace std; #define mpr make_pair #define rr first #define ii second const int N = 5e5+50; const int M = 25; const double Pi = M_PI; typedef pair< double,double > Complex; Complex operator + (const Complex &a,const Complex &b) { return mpr(a.rr+b.rr,a.ii+b.ii); } Complex operator - (const Complex &a,const Complex &b) { return mpr(a.rr-b.rr,a.ii-b.ii); } Complex operator * (const Complex &a,const Complex &b) { return mpr(a.rr*b.rr-a.ii*b.ii,a.rr*b.ii+a.ii*b.rr); } int n,m; Complex a[N],b[N],c[N]; int ans[N],pow2[M]; void init(int x) { pow2[0]=1; for(int i=1;i<M;i++) pow2[i]=pow2[i-1]<<1; for(m=0,n=1;n<x;n<<=1,m++); n<<=1,m++; } void Rev(Complex a[]) { for(int i=0,j=0;i<n;i++) { if(i>j) swap(a[i],a[j]); for(int k=n>>1;(j^=k)<k;k>>=1); } } void DFT(Complex y[],int r) { Rev(y); for(int i=2;i<=n;i<<=1) { Complex wi=mpr(cos(2.0*Pi/i),r*sin(2.0*Pi/i)); for(int k=0;k<n;k+=i) { Complex w=mpr(1.0,0.0); for(int j=k;j<k+i/2;j++) { Complex t1=y[j],t2=w*y[j+i/2]; y[j]=t1+t2,y[j+i/2]=t1-t2; w=w*wi; } } }if(r==-1) for(int i=0;i<n;i++) y[i].rr/=n; } void FFT(Complex a[],Complex b[],Complex c[]) { DFT(a,1),DFT(b,1); for(int i=0;i<n;i++) c[i]=a[i]*b[i]; DFT(c,-1); } int main() { string s1,s2; cin>>s1>>s2; reverse(s1.begin(),s1.end()); reverse(s2.begin(),s2.end()); init((int)max(s1.length(),s2.length())); for(int i=0;i<(int)s1.length();i++) a[i]=mpr(s1[i]-'0',0); for(int i=0;i<(int)s2.length();i++) b[i]=mpr(s2[i]-'0',0); FFT(a,b,c); for(int i=0;i<n;i++) ans[i]=c[i].rr+0.5; for(int i=0;i<n;i++) ans[i+1]+=ans[i]/10,ans[i]%=10; for(;!ans[n] && n;n--); for(int i=n;~i;i--) putchar(ans[i]+'0'); return 0; }
- FNT \(O(nlogn)\)
#include <bits/stdc++.h> using namespace std; typedef long long LL; const int N = 5e5+50; const int p = (479 << 21) + 1; const int g = 3; int n; LL a[N],b[N],c[N]; LL Pow(LL a,LL b,LL r=1) { for(;b;b>>=1,a=a*a%p) if(b&1) r=r*a%p;return r; } void init(int x) { for(n=1;n<x;n<<=1);n<<=1; } void Rev(LL a[]) { for(int i=0,j=0;i<n;i++) { if(i>j) swap(a[i],a[j]); for(int k=n>>1;(j^=k)<k;k>>=1); } } void FNT(LL y[],int r) { Rev(y); for(int i=2;i<=n;i<<=1) { LL wi=Pow(g,(p-1)/i); if(r==-1) wi=Pow(wi,p-2); for(int k=0;k<n;k+=i) { LL w=1; for(int j=k;j<k+i/2;j++) { LL t1=y[j],t2=(w*y[j+i/2])%p; y[j]=(t1+t2)%p,y[j+i/2]=(t1-t2+p)%p; w=w*wi%p; } } }if(r==-1) { LL inv=Pow(n,p-2); for(int i=0;i<n;i++) y[i]=y[i]*inv%p; } } void FFT(LL a[],LL b[],LL c[]) { FNT(a,1),FNT(b,1); for(int i=0;i<n;i++) c[i]=a[i]*b[i]%p; FNT(c,-1); } int main() { string s1,s2; cin>>s1>>s2; reverse(s1.begin(),s1.end());reverse(s2.begin(),s2.end()); for(int i=0;i<s1.length();i++) a[i]=s1[i]-'0'; for(int i=0;i<s2.length();i++) b[i]=s2[i]-'0'; init(max(s1.length(),s2.length())); FFT(a,b,c); for(int i=0;i<n;i++) c[i+1]=(c[i+1]+c[i]/10),c[i]=c[i]%10; int p=n;for(;!c[p] && p>0;p--); for(;~p;p--) printf("%d",c[p]); return 0; }
优化
- 读入优化
char *ps=(char *)malloc(20000000); inline LL in(LL x=0){ for(;*ps>'9'||*ps<'0';ps++); for(;*ps>='0'&&*ps<='9';ps++) x=(x<<3)+(x<<1)+*ps-'0';return x; } fread(ps,1,20000000,stdin);
- 输出优化
inline void Out(LL x){ int l=0;char ch[65]; if(!x){ putchar('0');return; } if(x<0) putchar('-'),x=-x; while(x) ch[++l]=x%10+'0',x/=10; for(int i=l;i;i--) putchar(ch[i]); }
计算几何
- qwq
#include <bits/stdc++.h> using namespace std; namespace CG { typedef long double LD; const LD Pi = M_PI; const LD PI = 2 * acos(0.0); const LD eps = 1e-18; const LD oo = 1e15; #define sqr(x) ((x)*(x)) int dcmp(LD x) { return fabs(x)<=eps?0:(x<0?-1:1); } struct Point { LD x,y; Point(LD _x=0,LD _y=0) :x(_x),y(_y) {} void out() { cout<<"("<<x<<","<<y<<")"; } }; typedef Point Vector; int cmpx(const Point &a,const Point &b) { return dcmp(a.x-b.x)==0?a.y<b.y:a.x<b.x; } Vector operator + (const Vector &a,const Vector &b) { return Vector(a.x+b.x,a.y+b.y); } Vector operator - (const Vector &a,const Vector &b) { return Vector(a.x-b.x,a.y-b.y); } Vector operator * (const Vector &a,LD b) { return Vector(a.x*b,a.y*b); } Vector operator / (const Vector &a,LD b) { return Vector(a.x/b,a.y/b); } bool operator == (const Point &a,const Point &b) { return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0; } LD Dot(Vector a,Vector b) { return a.x*b.x+a.y*b.y; } LD Cross(Vector a,Vector b) { return a.x*b.y-b.x*a.y; } Vector Rot(Vector a,LD rd) { return Vector(a.x*cos(rd)-a.y*sin(rd),a.x*sin(rd)+a.y*cos(rd)); } LD get_l(Vector a) { return sqrt(Dot(a,a)); } LD get_d(Point a,Point b) { return sqrt(Dot(a-b,a-b)); } LD get_a(Vector a) { return atan2(a.y,a.x); } LD get_a(Vector a,Vector b) { return acos(Dot(a,b)/get_l(a)/get_l(b)); } LD get_s(Point a,Point b,Point c) { return Cross(b-a,c-a)/2.0; } struct Line { Point p; Vector v; LD ang; Line(Point _p=Point(),Vector _v=Vector()):p(_p),v(_v) { ang=get_a(v); } LD get_l() { return sqrt(Dot(v,v)); } Point get_p(LD t) { return p+v*t; } Point get_s() { return p; } Point get_t() { return p+v; } int chkleft(Point P) { return dcmp(Cross(v,P-p))>0; } }; int cmpa(const Line &a,const Line &b) { return dcmp(a.ang-b.ang)==-1; } Point get_l_l(Line a,Line b) { Vector u=a.p-b.p; LD t=Cross(b.v,u)/Cross(a.v,b.v); return a.get_p(t); } typedef Line Hp; int get_h_h(vector<Hp> &hs,vector<Point> &pt) { sort(hs.begin(),hs.end(),cmpa); vector<Point> p(hs.size()); vector<Hp> q(hs.size()); int h,t; q[h=t=0]=hs[0]; for(int i=1;i<(int)hs.size();i++) { while(h<t && !hs[i].chkleft(p[t-1])) t--; while(h<t && !hs[i].chkleft(p[h])) h++; q[++t]=hs[i]; if(fabs(Cross(q[t].v,q[t-1].v))<eps) { t--; if(q[t].chkleft(hs[i].p)) q[t]=hs[i]; } if(h<t) p[t-1]=get_l_l(q[t-1],q[t]); } while(h<t && !q[h].chkleft(p[t-1])) t--; p[t]=get_l_l(q[h],q[t]); for(int i=h;i<=t;i++) pt.push_back(p[i]); return t-h+1; } struct Circle { Point c; LD r; Point get_p(LD t) { return c+Point(cos(t)*r,sin(t)*r); } LD get_rd(Point a,Point b) { return get_a(a-c,b-c); } LD get_l(LD rd) { return r*rd; } }; int get_c_l(Line L,Circle C,vector<Point> &res) { LD a=L.v.x,b=L.p.x-C.c.x,c=L.v.y,d=L.p.y-C.c.y; LD e=sqr(a)+sqr(c),f=2.0*(a*b+c*d),g=sqr(b)+sqr(d)-sqr(C.r); LD dt=f*f-4*e*g; if(dcmp(dt)<0) return 0; if(dcmp(dt)==0) return res.push_back(L.get_p(-f/(2.0*e))),1; LD x1=(-f-sqrt(dt))/(2.0*e),x2=(-f+sqrt(dt))/(2.0*e); if(x1>x2) swap(x1,x2); res.push_back(L.get_p(x1)),res.push_back(L.get_p(x2));return 2; } int get_c_c(Circle A,Circle B,vector<Point> &res) { LD d=get_l(A.c-B.c); if(dcmp(d)==0) return dcmp(A.r-B.r)==0?-1:0; if(dcmp(A.r+B.r-d)<0) return 0; if(dcmp(fabs(A.r-B.r)-d)>0) return 0; LD a=get_a(B.c-A.c); LD rd=acos((sqr(A.r)+sqr(d)-sqr(B.r))/(2.0*A.r*d)); Point p1,p2; p1=A.get_p(a+rd),p2=A.get_p(a-rd); res.push_back(p1); if(p1==p2) return 1; res.push_back(p2); return 2; } /*---io---*/ ostream & operator << (ostream &os,const Point &p) { os<<p.x<<" "<<p.y;return os; } istream & operator >> (istream &is,Point &p) { is>>p.x>>p.y;return is; } ostream & operator << (ostream &os,const Circle &C) { os<<C.c<<" "<<C.r;return os; } istream & operator >> (istream &is,Circle &C) { is>>C.c>>C.r;return is; } }; int main() { }
图论
- Tarjan-割点 \(O(m)\)
#include<cstdio> #include<vector> #include<iostream> using namespace std; const int N = 100005; #define debug(a) cout<<#a<<"="<<a<<" " int n,m,cnt,ans; vector<int> g[N]; int b[N],out[N],du[N]; int dfsn[N],low[N]; inline int in(int x=0,char ch=getchar()){ while(ch>'9'||ch<'0') ch=getchar(); while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x; } void Tarjan(int u,int fa){ dfsn[u]=low[u]=++cnt;int c=0; for(int i=0,v;i<du[u];i++) if((v=g[u][i])!=fa){ if(!dfsn[v]){ Tarjan(v,u),low[u]=min(low[u],low[v]),c++; if(fa>0&&dfsn[u]<=low[v]) b[u]=1; }else low[u]=min(low[u],dfsn[v]); }if(fa==0&&c>1) b[u]=1; } int main(){ n=in(),m=in(); for(int i=1,u,v;i<=m;i++) u=in(),v=in(),du[u]++,du[v]++,g[u].push_back(v),g[v].push_back(u); for(int i=1;i<=n;i++) if(!dfsn[i]) Tarjan(i,0); for(int i=1;i<=n;i++) if(b[i]) out[++ans]=i; printf("%d\n",ans); for(int i=1;i<=ans;i++) printf("%d ",out[i]);putchar('\n'); return 0; }
- Tarjan-割边(桥) \(O(m)\)
#include<cstdio> #include<vector> #include<iostream> using namespace std; const int N = 100005; #define mpr(a,b) make_pair(a,b) int n,m,cnt,ans; int iscut[N],e[N]; int dfsn[N],low[N]; struct Edge{ int fr,to,id; }edge[N]; vector<Edge> g[N]; inline int in(int x=0,char ch=getchar()){ while(ch>'9'||ch<'0') ch=getchar(); while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x; } inline void Add_Edge(int u,int v,int id){ edge[id]=(Edge){ u,v,id }; g[u].push_back((Edge){ u,v,id }); g[v].push_back((Edge){ v,u,id }); } void Tarjan(int u,int fa){ dfsn[u]=low[u]=++cnt; for(int i=0,lim=g[u].size(),v;i<lim;i++) if((v=g[u][i].to)!=fa){ if(!dfsn[v]){ Tarjan(v,u); if(low[v]>dfsn[u]) iscut[g[u][i].id]=1; low[u]=min(low[u],low[v]); }else low[u]=min(low[u],dfsn[v]); } } int main(){ n=in(),m=in(); for(int i=1,u,v;i<=m;i++) u=in(),v=in(),Add_Edge(u,v,i); for(int i=1;i<=n;i++) if(!dfsn[i]) Tarjan(i,0); for(int i=1;i<=m;i++) if(iscut[i]) e[++ans]=i; printf("%d\n",ans); for(int i=1;i<=ans;i++) printf("%d\n",e[i]); return 0; }
- Tarjan-强连通分量+缩点. \(O(m)\)
#include<cstdio> #include<stack> #include<vector> #include<iostream> using namespace std; const int N = 10005; #define debug(a) cout<<#a<<"="<<a<<" " #define ct cout<<endl #define _ct cout<<"----------"<<endl int n,m,cnt,bcnt; int dfsn[N],low[N],ins[N],b[N],sz[N]; vector<int> g[N]; vector<int> h[N]; stack<int> stk; struct Edge{ int fr,to; }edge[N*5]; inline int in(int x=0,char ch=getchar()){ while(ch>'9'||ch<'0') ch=getchar(); while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x; } void Tarjan(int u){ dfsn[u]=low[u]=++cnt,ins[u]=1,stk.push(u); for(int i=0,lim=g[u].size(),v;i<lim;i++){ v=g[u][i]; if(!dfsn[v]){ Tarjan(v),low[u]=min(low[u],low[v]); } else if(ins[v]) low[u]=min(low[u],dfsn[v]); }if(dfsn[u]==low[u]){ ++bcnt;int v; for(;;){ v=stk.top(),stk.pop(),ins[v]=0,b[v]=bcnt,sz[bcnt]++;if(u==v) break; } } } int main(){ // freopen("in.in","r",stdin); n=in(),m=in(); for(int i=1,u,v;i<=m;i++) u=in(),v=in(),g[u].push_back(v),edge[i]=(Edge){ u,v }; for(int i=1;i<=n;i++) if(!dfsn[i]) Tarjan(i); // _ct;debug(bcnt),ct; for(int i=1,u,v;i<=m;i++){ u=edge[i].fr,v=edge[i].to; // debug(u),debug(v),ct; // debug(b[u]),debug(b[v]),ct; if(b[u]!=b[v]) h[b[u]].push_back(b[v]); }return 0; }
- LCA-倍增 \(O(nlogn+mlogn)\)
#include<cstdio> #include<utility> #include<vector> #include<iostream> using namespace std; #define mpr make_pair #define debug(a) cout<<#a<<"="<<a<<" " typedef pair< int,int > pr; const int N = 50005; const int M = 31; int n,m,k; vector<pr> h[N]; int pow2[M],d[N]; int f[N][M],g[N][M]; inline int in(int x=0,char ch=getchar()){ while(ch>'9' || ch<'0') ch=getchar(); while(ch>='0' && ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x; } void DFS(int u,int fa,int dep){ d[u]=dep; for(int i=0,v;i<h[u].size();i++) if((v=h[u][i].first)!=fa){ DFS(v,u,dep+1),f[v][0]=u,g[v][0]=h[u][i].second; } } void work(){ pow2[0]=1;for(int i=1;i<M;i++) pow2[i]=pow2[i-1]<<1; for(int j=1;j<M;j++) for(int i=0;i<n;i++) f[i][j]=f[f[i][j-1]][j-1],g[i][j]=g[i][j-1]+g[f[i][j-1]][j-1]; } int Dis(int u,int v){ if(d[u]<d[v]) swap(u,v); int l=d[u]-d[v],res=0; if(l) for(int i=0;i<M;i++) if(l&pow2[i]) res+=g[u][i],u=f[u][i]; if(u==v) return res; for(int i=M-1;~i;--i){ if(f[u][i]!=f[v][i]) res+=g[u][i]+g[v][i],u=f[u][i],v=f[v][i]; }return g[u][0]+g[v][0]+res; } int main(){ n=in(); for(int i=1,u,v,w;i<n;i++) u=in(),v=in(),w=in(),h[u].push_back(mpr(v,w)),h[v].push_back(mpr(u,w)); DFS(0,0,1); work(); for(k=in();k--;){ int u=in(),v=in(); printf("%d\n",Dis(u,v)); }return 0; }
- LCA-ST表 \(O(nlogn+m)\)
#include<cstdio> #include<cmath> #include<cstring> #include<utility> #include<vector> #include<iostream> using namespace std; #define debug(a) cout<<#a<<"="<<a<<" " #define mpr make_pair typedef pair< int,int > pr; const int N = 200005; const int M = 25; int n,m,cnt; vector< pr > g[N]; int pow2[M],dfs[N],d[N],val[N],pos[N],lg2[N]; int f[N][M]; inline int in(int x=0,char ch=getchar()){ while(ch>'9' || ch<'0') ch=getchar(); while(ch>='0' && ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x; } void DFS(int u,int fa,int dep,int value){ dfs[++m]=u,d[u]=dep,val[u]=value,pos[u]=m,f[m][0]=u; for(int i=0,v;i<g[u].size();i++) if((v=g[u][i].first)!=fa) DFS(v,u,dep+1,value+g[u][i].second),dfs[++m]=u,f[m][0]=u; } void init(){ pow2[0]=1;for(int i=1;i<M;i++) pow2[i]=pow2[i-1]<<1; lg2[0]=-1;for(int i=1;i<=m;i++) lg2[i]=lg2[i>>1]+1; for(int j=1;j<M;j++) for(int i=1;i<=m;i++) if(i+pow2[j]-1<=m){ int u=f[i][j-1],v=f[i+pow2[j-1]][j-1]; if(d[u]<d[v]) f[i][j]=u;else f[i][j]=v; } } int Dis(int u,int v,int lca=0){ if(pos[u]<pos[v]) swap(u,v); int lg=lg2[pos[u]-pos[v]+1]; if(d[f[pos[v]][lg]]<d[f[pos[u]-pow2[lg]+1][lg]]) lca=f[pos[v]][lg];else lca=f[pos[u]-pow2[lg]+1][lg]; return val[u]+val[v]-2*val[lca]; } int main(){ memset(d,0x3f,sizeof(d)); n=in(); for(int i=1,u,v,w;i<n;i++) u=in(),v=in(),w=in(),g[u].push_back(mpr(v,w)),g[v].push_back(mpr(u,w)); DFS(0,0,1,0),init(); for(int k=in(),u,v;k--;){ u=in(),v=in(); printf("%d\n",Dis(u,v)); }return 0; }
- 网络流-ISAP \(O(V^{2}E)\)
#include<cstdio> #include<cstring> #include<vector> #include<queue> #include<iostream> using namespace std; const int INF = 0x7fffffff; const int N = 505; const int M = 805; inline int in(int x=0,char ch=getchar()){ while(ch>'9'||ch<'0') ch=getchar(); while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x; } struct NetWork{ int n,m,s,t; struct Edge{ int fr,to,flow; }edge[M<<1];int cnte; vector<int> g[N];int flow; int num[N],cur[N],d[N],p[N];bool v[N]; void Add_Edge(int fr,int to,int fl){ edge[cnte++]=(Edge){ fr,to,fl },edge[cnte++]=(Edge){ to,fr,0 }; g[fr].push_back(cnte-2),g[to].push_back(cnte-1); } int Add_Flow(){ int a=INF; for(int x=t;x!=s;x=edge[p[x]].fr) a=min(a,edge[p[x]].flow); for(int x=t;x!=s;x=edge[p[x]].fr) edge[p[x]].flow-=a,edge[p[x]^1].flow+=a; return a; } void BFS(){ for(int i=1;i<=n;i++) d[i]=n; memset(v,0,sizeof(v)); queue<int> q;q.push(t),v[t]=1,d[t]=0; for(int x;!q.empty();){ x=q.front(),q.pop(); for(int i=0,lim=g[x].size();i<lim;i++){ Edge &e=edge[g[x][i]]; Edge &u=edge[g[x][i]^1]; if(!v[e.to]&&u.flow) d[e.to]=d[x]+1,v[e.to]=1,q.push(e.to); } } } int ISAP(){ BFS();int flow=0; memset(num,0,sizeof(num)),memset(cur,0,sizeof(cur)); for(int i=1;i<=n;i++) num[d[i]]++; for(int x=s,ok;d[s]<n;){ if(x==t) flow+=Add_Flow(),x=s;ok=0; for(int &i=cur[x],lim=g[x].size();i<lim;i++){ Edge &e=edge[g[x][i]]; if(e.flow&&d[x]==d[e.to]+1){ ok=1,p[e.to]=g[x][i],x=e.to;break; } } if(!ok){ int tmp=n-1; for(int i=0,lim=g[x].size();i<lim;i++) tmp=min(tmp,d[edge[g[x][i]].to]); if(!(--num[d[x]])) break;num[d[x]=m+1]++,cur[x]=0; if(x!=s) x=edge[p[x]].fr; } }return flow; } }isap; int main(){ return 0; }
- 网络流-Dinic \(O(VE^{2})\)/二分图\(O(\sqrt{V}E)\)
#include<cstdio> #include<queue> #include<cstring> #include<vector> #include<iostream> using namespace std; const int N = 505; const int INF = 0x7fffffff; int T,n,m,cnt,ans; struct NetWork{ int n,m,s,t,flow; struct Edge{ int fr,to,flow; }; vector<Edge> edge;vector<int> g[N]; int cur[N],d[N],p[N]; void Add_Edge(int fr,int to,int flow){ edge.push_back((Edge){ fr,to,flow }); edge.push_back((Edge){ to,fr,0 }); m=edge.size(); g[fr].push_back(m-2),g[to].push_back(m-1); } int BFS(){ memset(d,-1,sizeof(d)); queue<int> q;q.push(s),d[s]=0; for(int x;!q.empty();){ x=q.front(),q.pop(); for(int i=0,lim=g[x].size();i<lim;i++){ Edge &e=edge[g[x][i]]; if(e.flow&&d[e.to]==-1) d[e.to]=d[x]+1,q.push(e.to); } }return d[t]!=-1; } int Dinic(){ flow=0; for(int x,k;BFS();){ memset(cur,0,sizeof(cur));x=s,k=0; for(int ok;;){ if(x==t){ int mine=-1,minf=0x7fffffff; for(int i=0;i<k;i++) if(edge[p[i]].flow<minf) minf=edge[p[i]].flow,mine=i; for(int i=0;i<k;i++) edge[p[i]].flow-=minf,edge[p[i]^1].flow+=minf; x=edge[p[mine]].fr,k=mine,flow+=minf; }ok=0; for(int &i=cur[x],lim=g[x].size();i<lim;i++){ Edge &e=edge[g[x][i]]; if(e.flow>0&&d[x]+1==d[e.to]){ p[k++]=g[x][i],x=e.to,ok=1;break; } } if(!ok){ if(!k) break;d[x]=-1,x=edge[p[--k]].fr; } } }return flow; } }dinic; int main(){ return 0; }
- 最小生成树计数Matrix-Tree定理 \(O(n^3)\)
#include<cstdio> #include<cstring> #include<iostream> using namespace std; const double eps = 1e-8; const int N = 105; #define _0(x) ((x>0?x:-x)+eps>0) int n,m; int g[N][N],d[N]; double a[N][N]; double det(int n){ double res=1;int swpt=0; for(int i=0,j,k;i<n;i++){ if(!_0(a[i][i])){ for(j=i+1;j<n;j++) if(_0(a[j][i])) break; if(j>=n) return 0; for(k=i;k<n;k++) swap(a[i][k],a[j][k]); swpt++; }res*=a[i][i]; // for(j=i+1;j<n;j++) a[i][j]/=a[i][i]; for(j=i+1;j<n;j++) for(k=i+1;k<n;k++) a[j][k]-=a[j][i]*a[i][k]/a[i][i]; if(swpt&1) return -res;return res; } inline int in(int x=0,char ch=getchar()){ while(ch>'9'||ch<'0') ch=getchar(); while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x; } int main(){ for(int T=in();T--;){ n=in(),m=in();memset(a,0,sizeof(a)),memset(g,0,sizeof(g)),memset(d,0,sizeof(d)); for(int i=1,u,v;i<=m;i++) u=in()-1,v=in()-1,g[u][v]=g[v][u]=1,d[u]++,d[v]++; for(int i=0;i<n;i++) a[i][i]=d[i]; for(int i=0;i<n;i++) for(int j=0;j<n;j++) if(g[i][j]) a[i][j]-=1; // for(int i=0;i<n;i++) for(int j=0;j<n;j++) printf("%.0lf%c",a[i][j]," \n"[j==n-1]); printf("%.0lf\n",det(n-1)); // for(int i=0;i<n;i++) for(int j=0;j<n;j++) printf("%.0lf%c",a[i][j]," \n"[j==n-1]); }return 0; }
- 曼哈顿最小生成树 \(O(n logn)\)
#include<cstdio> #include<cstring> #include<vector> #include<utility> #include<queue> #include<algorithm> #include<iostream> using namespace std; #define mpr(a,b) make_pair(a,b) const int N = 50005; int n,ans; struct seat{ int x,y,id; }a[N],b[N]; bool operator < (const seat &a,const seat &b){ return a.x==b.x?a.y>b.y:a.x>b.x; } int d[N<<1],id[N<<1],cnt,ys[N]; struct Edge{ int u,v,w; }; bool operator < (const Edge &a,const Edge &b){ return a.w>b.w; } priority_queue<Edge> q; int f[N]; inline int in(int x=0,char ch=getchar(),int v=1){ while(ch!='-'&&(ch>'9'||ch<'0')) ch=getchar();if(ch=='-') v=-1,ch=getchar(); while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x*v; } //int cmpx(const seat &a,const seat &b){ return a.x==b.x?a.x<b.x:a.y<b.y; } //int cmpxy(const seat &a,const seat &b){ return a.y-a.x<b.y-b.x; } inline int abs(int x){ return x<0?-x:x; } int find(int x){ return f[x]==x?x:f[x]=find(f[x]); } void Add_Edge(int u,int v){ int dis=abs(a[u].x-a[v].x)+abs(a[u].y-a[v].y); q.push((Edge){ u,v,dis }); } void Add(int x,int v,int pos){ for(;x;x-=x&-x) if(d[x]>v) d[x]=v,id[x]=pos; } int Query(int x){ int minv=0x7f7f7f7f,pos=-1; for(;x<=cnt;x+=x&-x) if(d[x]<minv) minv=d[x],pos=id[x]; return pos; } void out(seat a){ cout<<a.x<<" "<<a.y<<" "<<a.id<<endl<<"***************\n"; } void Build(){ /* Part1 x1>x0&&y1-x1>y0-x0 dis=(x1+y1)-(x0+y0) */ memset(d,0x7f,sizeof(d)),memset(id,-1,sizeof(id)),memset(ys,0,sizeof(ys));cnt=0; for(int i=1;i<=n;i++) b[i]=a[i]; // for(int i=1;i<=n;i++) out(a[i]); sort(b+1,b+n+1); // for(int i=1;i<=n;i++) out(b[i]); for(int i=1;i<=n;i++) ys[i]=b[i].y-b[i].x; sort(ys+1,ys+n+1); cnt=unique(ys+1,ys+n+1)-ys-1; // cout<<cnt<<endl; // for(int i=1;i<=cnt;i++) cout<<ys[i]<<" ";cout<<endl; for(int i=1;i<=n;i++){ int x=lower_bound(ys+1,ys+cnt+1,b[i].y-b[i].x)-ys; int pos=Query(x); if(~pos) Add_Edge(b[i].id,pos); // cout<<b[i].id<<"-->"<<pos<<endl; Add(x,b[i].x+b[i].y,b[i].id); } /* Part2 swap(x,y) */ memset(d,0x7f,sizeof(d)),memset(id,-1,sizeof(id)),memset(ys,0,sizeof(ys));cnt=0; for(int i=1;i<=n;i++) b[i].y=a[i].x,b[i].x=a[i].y,b[i].id=a[i].id; sort(b+1,b+n+1); // for(int i=1;i<=n;i++) out(b[i]); for(int i=1;i<=n;i++) ys[i]=b[i].y-b[i].x; sort(ys+1,ys+n+1); cnt=unique(ys+1,ys+n+1)-ys-1; // cout<<cnt<<endl; // for(int i=1;i<=cnt;i++) cout<<ys[i]<<" ";cout<<endl; for(int i=1;i<=n;i++){ int x=lower_bound(ys+1,ys+cnt+1,b[i].y-b[i].x)-ys; int pos=Query(x); if(~pos) Add_Edge(b[i].id,pos); // cout<<b[i].id<<"-->"<<pos<<endl; Add(x,b[i].x+b[i].y,b[i].id); } /* Part3 y=-y */ memset(d,0x7f,sizeof(d)),memset(id,-1,sizeof(id)),memset(ys,0,sizeof(ys));cnt=0; for(int i=1;i<=n;i++) b[i]=a[i],b[i].y=-b[i].y; sort(b+1,b+n+1); // for(int i=1;i<=n;i++) out(b[i]); for(int i=1;i<=n;i++) ys[i]=b[i].y-b[i].x; sort(ys+1,ys+n+1); cnt=unique(ys+1,ys+n+1)-ys-1; // cout<<cnt<<endl; // for(int i=1;i<=cnt;i++) cout<<ys[i]<<" ";cout<<endl; for(int i=1;i<=n;i++){ int x=lower_bound(ys+1,ys+cnt+1,b[i].y-b[i].x)-ys; int pos=Query(x); if(~pos) Add_Edge(b[i].id,pos); // cout<<b[i].id<<"-->"<<pos<<endl; Add(x,b[i].x+b[i].y,b[i].id); } /* Part4 swap(x,y) y=-y */ memset(d,0x7f,sizeof(d)),memset(id,-1,sizeof(id)),memset(ys,0,sizeof(ys));cnt=0; for(int i=1;i<=n;i++) b[i].x=-a[i].y,b[i].y=a[i].x,b[i].id=a[i].id; sort(b+1,b+n+1); // for(int i=1;i<=n;i++) out(b[i]); for(int i=1;i<=n;i++) ys[i]=b[i].y-b[i].x; sort(ys+1,ys+n+1); cnt=unique(ys+1,ys+n+1)-ys-1; // cout<<cnt<<endl; // for(int i=1;i<=cnt;i++) cout<<ys[i]<<" ";cout<<endl; for(int i=1;i<=n;i++){ int x=lower_bound(ys+1,ys+cnt+1,b[i].y-b[i].x)-ys; int pos=Query(x); if(~pos) Add_Edge(b[i].id,pos); // cout<<b[i].id<<"-->"<<pos<<endl; Add(x,b[i].x+b[i].y,b[i].id); } /* MST */ for(int i=1;i<=n;i++) f[i]=i; for(int k=1;!q.empty();){ Edge e=q.top();q.pop(); int u=e.u,v=e.v; int f1=find(u),f2=find(v); if(f1!=f2) k++,f[f2]=f1,ans+=e.w; if(k>=n) break; }cout<<ans<<endl; } int main(){ // freopen("in.in","r",stdin); // freopen("out.out","w",stdout); n=in();for(int i=1;i<=n;i++) a[i].x=in(),a[i].y=in(),a[i].id=i; Build(); return 0; }
- 朱刘算法/最小树形图 \(O(nm)\)
#include <bits/stdc++.h> using namespace std; inline int in(int x=0,char ch=getchar()) { while(ch>'9' || ch<'0') ch=getchar(); while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();return x; } const int N = 55; const int M = N*N+50; struct Edge { int fr,to;double v; }; Edge edge[M]; int n,m,rt; int b[N]; double mic[N]; double miv[N]; int pre[N],vis[N],id[N]; void AddEdge(int fr,int to,double v) { edge[++m]=(Edge){ fr,to,v }; } double Solve(int n) { double res=0; for(int cnt,tmp;;) { for(int i=1;i<=n;i++) miv[i]=1e9,pre[i]=0; for(int i=1;i<=m;i++) { Edge &e=edge[i]; if(e.v<miv[e.to]) miv[e.to]=e.v,pre[e.to]=e.fr; } for(int i=1;i<=n;i++) if(pre[i]) res+=miv[i]; memset(vis,0,sizeof(vis)); memset(id,0,sizeof(id)); vis[0]=tmp=1,cnt=0; for(int i=1;i<=n;i++) if(!vis[i]) { ++tmp;int u=i; for(;!vis[u];u=pre[u]) vis[u]=tmp; if(vis[u]==tmp) { ++cnt; for(;!id[u];u=pre[u]) id[u]=cnt; } } if(!cnt) break; for(int i=1;i<=n;i++) if(!id[i]) id[i]=++cnt; int mm=m;m=0; for(int i=1;i<=mm;i++) { Edge &e=edge[i]; if(id[e.fr]!=id[e.to]) AddEdge(id[e.fr],id[e.to],e.v-miv[e.to]); } n=cnt; }return res; } int main() { n=in(),rt=n+1; for(int i=1;i<=n;i++) { double x;scanf("%lf",&x); mic[i]=x; b[i]=in(); if(b[i]) AddEdge(rt,i,x); } for(int k=in();k--;) { int x=in(),y=in(); double z;scanf("%lf",&z); if(b[x] && b[y]) { AddEdge(x,y,z); mic[y]=min(mic[y],z); } } double ans=Solve(n+1); // cout<<ans<<endl; // for(int i=1;i<=n;i++) cout<<mic[i]<<" ";cout<<endl; for(int i=1;i<=n;i++) if(b[i]) ans+=(b[i]-1)*mic[i]; printf("%.2lf\n",ans); return 0; }
数学
- 快速幂 \(O(logn)\) 快速乘 \(O(1)\)
inline LL Mul(LL a,LL b,LL p){ if(p<=1000000000) return a*b%p; return (a*b-(LL)(a/(long double)p*b+1e-3)*p+p)%p; // for(;b;b>>=1,a=(a+a)%p) if(b&1) res=(res+a)%p;return res; } inline LL Pow(LL a,LL b,LL p,LL res=1){ for(;b;b>>=1,a=Mul(a,a,p)) if(b&1) res=Mul(res,a,p);return res; }
-
\(\varphi(n)\) \(O(\sqrt{n})\)
inline LL GetPhi(LL p){ LL res=p,m=sqrt(p)+0.5; for(int i=2;i<=m;i++) if(p%i==0){ res=res/i*(i-1); while(p%i==0) p/=i; } if(p>1) res=res/p*(p-1);return res; }
- 线性筛 \(\mu\) \(O(n)\)
#include<cstdio> #include<cmath> #include<iostream> using namespace std; const int N = 1000005; int mu[N],pr[N],cnt; bool b[N]; void Pre(){ mu[1]=1; for(int i=2;i<=N;i++){ if(!b[i]) mu[i]=-1,pr[++cnt]=i; for(int j=1;j<=cnt&&pr[j]*i<=N;j++){ b[i*pr[j]]=1; if(i%pr[j]) mu[i*pr[j]]=-mu[i]; else break; } } // for(int i=1;i<=10;i++) cout<<mu[i]<<" ";cout<<endl; } int main(){ Pre();return 0; }
- 矩阵乘法和矩阵快速幂 \(O(n^3) O(n^3 logn)\)
#include<cstdio> #include<vector> #include<iostream> using namespace std; typedef long long LL; typedef vector<LL> Vec; typedef vector<Vec> Mat; const LL p = 10000000007LL; Mat operator * (const Mat &A,const Mat &B){ Mat C(A.size(),Vec(B[0].size())); for(int i=0;i<A.size();i++) for(int j=0;j<B[0].size();j++) for(int k=0;k<A[0].size();k++) C[i][j]=(C[i][j]+A[i][k]*B[k][j])%p; return C; } Mat operator ^ (Mat A,LL b){ Mat res(A.size(),Vec(A[0].size())); for(int i=0;i<A.size();i++) for(int j=0;j<A[0].size();j++) res[i][j]=(i==j)?1:0; for(;b;b>>=1,A=A*A) if(b&1) res=res*A; return res; } int main(){ return 0; }
- 扩展欧几里得 \(O(logn)\)
LL Exgcd(LL a,LL b,LL &x,LL &y){ if(!b){ x=1,y=0;return a; } LL r=Exgcd(b,a%b,x,y);LL t=x; x=y,y=t-(a/b)*y;return r; }
- 中国剩余定理 \(O(nlogn)\)
#include<cstdio> #include<iostream> using namespace std; typedef long long LL; const int N = 1005; int n; LL m[N],a[N]; LL Exgcd(LL a,LL b,LL &x,LL &y){ if(!b){ x=1,y=0;return a; } LL r=Exgcd(b,a%b,x,y);LL t=x; x=y,y=t-(a/b)*y;return r; } LL Solve(){ LL M=m[1],MM,res=0,x,y; for(int i=2;i<=n;i++) M*=m[i]; for(int i=1;i<=n;i++){ MM=M/m[i]; Exgcd(MM,m[i],x,y); res=(res+MM*x*a[i])%M; }return res; } int main(){ cin>>n; for(int i=1;i<=n;i++) cin>>m[i]>>a[i]; Solve(); return 0; }
- 求解模线性方程组 \(O(nlogn)\)
#include<cstdio> #include<utility> #include<algorithm> #include<iostream> using namespace std; typedef long long LL; #define mpr make_pair const int N = 1005; LL n,a1,a2,b1,b2; pair< LL,LL > m[N]; inline LL in(LL x=0,char ch=getchar()){ while(ch>'9' || ch<'0') ch=getchar(); while(ch>='0' && ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x; } LL Exgcd(LL a,LL b,LL &x,LL &y){ if(!b){ x=1,y=0;return a; } LL r=Exgcd(b,a%b,x,y);LL t=x; x=y,y=t-(a/b)*y;return r; } int Solve(){ LL x,y,d=Exgcd(a1,a2,x,y); if((b2-b1)%d) return 0; Exgcd(a1/d,a2/d,x,y),x*=(b2-b1)/d,x=(x%(a2/d)+a2/d)%(a2/d); b1=a1*x+b1,a1=a1/d*a2,b1=(b1%a1+a1)%a1; return 1; } int main(){ n=in(); for(LL i=1,u,v;i<=n;i++) u=in(),v=in(),m[i]=mpr(u,v); a1=m[1].first,b1=m[1].second; for(int i=2;i<=n;i++){ a2=m[i].first,b2=m[i].second; if(!Solve()) return puts("-1"),0; }return printf("%lld\n",b1),0; }
字符串
- 后缀数组 \(O(nlogn)\)
#include <bits/stdc++.h> using namespace std; const int N = 200050; int n,m=26; char s[N]; int a[N]; namespace SuffixArray { int s1[N],s2[N],sa[N],rk[N],ht[N],c[N]; void get_sa(int a[],int n=::n,int m=::m) { int *x=s1,*y=s2; for(int i=1;i<=n;i++) c[x[i]=a[i]]++; for(int i=1;i<=m;i++) c[i]+=c[i-1]; for(int i=n;i;--i) sa[c[a[i]]--]=i; for(int k=1,p=0;k<n;k<<=1,p=0) { for(int i=n-k+1;i<=n;i++) y[++p]=i; for(int i=1;i<=n;i++) if(sa[i]>k) y[++p]=sa[i]-k; for(int i=0;i<=m;i++) c[i]=0; for(int i=1;i<=n;i++) c[x[i]]++; for(int i=1;i<=m;i++) c[i]+=c[i-1]; for(int i=n;i;--i) sa[c[x[y[i]]]--]=y[i]; swap(x,y);x[sa[1]]=p=1; for(int i=2;i<=n;i++) x[sa[i]]=(y[sa[i]]==y[sa[i-1]] && y[sa[i]+k]==y[sa[i-1]+k])?p:++p; if(p>=n) break; m=p; } } void get_ht(int a[],int n=::n) { for(int i=1;i<=n;i++) rk[sa[i]]=i; for(int i=1,k=0,j;i<=n;ht[rk[i++]]=k) for(j=sa[rk[i]-1],k=k?k-1:k;a[i+k]==a[j+k];k++); } } int main() { scanf("%s",s+1),n=strlen(s+1); for(int i=1;i<=n;i++) a[i]=s[i]-'a'+1; using namespace SuffixArray; get_sa(a);get_ht(a); for(int i=1;i<=n;i++) printf("%d%c",sa[i]," \n"[i==n]); // for(int i=1;i<=n;i++) cout<<rk[i]<<" ";cout<<endl; for(int i=2;i<=n;i++) printf("%d%c",ht[i]," \n"[i==n]); return 0; }
- Manacher \(O(n)\) 寻找最长回文串
#include<cstdio> #include<cstring> #include<iostream> using namespace std; const int N = 1000005; int p[N]; char s[N]; char ch[N]; int Manacher(char s[]){ int l=strlen(s+1),mx=0,res=0,id=0; // cout<<l<<endl; memset(p,0,sizeof(p)); for(int i=1;i<=l;i++){ if(mx>i) p[i]=min(p[id*2-i],mx-i); else p[i]=1; while(s[i+p[i]]==s[i-p[i]]) p[i]++; if(mx<i+p[i]) mx=i+p[i],id=i; } for(int i=1;i<=l;i++) res=max(p[i],res); // for(int i=1;i<=l;i++) cout<<p[i]<<" ";cout<<endl; return res-1; } int main(){ cin>>(s+1);ch[0]='$';ch[1]='#'; for(int i=1;i<=strlen(s+1);i++) ch[i*2]=s[i],ch[i*2+1]='#'; // cout<<(ch+1)<<endl; cout<<Manacher(ch)<<endl; return 0; }
- 后缀自动机(SAM) \(O(n)\)
#include<cstdio> #include<cstring> #include<iostream> using namespace std; const int N = 250005; struct State{ State *par,*go[26]; int val; State(int _val):par(0),val(_val){ memset(go,0,sizeof(go)); } }*rt,*lst; void extend(int w){ State *p=lst,*np=new State(p->val+1); while(p && p->go[w]==0) p->go[w]=np,p=p->par; if(!p) np->par=rt; else{ State *q=p->go[w]; if(q->val == p->val+1) np->par=q; else{ State *nq=new State(p->val+1); memcpy(nq->go,q->go,sizeof(q->go)); nq->par=q->par; np->par=q->par=nq; while(p && p->go[w]==q) p->go[w]=nq,p=p->par; } }lst=np; } int main(){ rt=new State(0),lst=rt; }
数据结构
- Treap \(O(n\log n)\)
#include <bits/stdc++.h> using namespace std; #define debug(a) cout<<(#a)<<"="<<a<<" " #define lc(o) ch[o][0] #define rc(o) ch[o][1] #define uor(i,j,k) for(int i=j;i<=(int)k;i++) #define uep(i,j,k) for(int i=j;i<(int)k;i++) #define dor(i,j,k) for(int i=j;i>=(int)k;i--) typedef long long ll; typedef pair<int,int> pr; typedef vector<int> vi; typedef vector<ll> vl; typedef vector<string> vs; const int N = 100050; const int M = 25; const int oo = 0x3fffffff; const ll OO = 1e18; const ll p = 1000000007; ll Pow(ll a,ll b,ll r=1) { for(;b;b>>=1,a=a*a%p) if(b&1) r=r*a%p;return r; } ll Pow(ll a,ll b,ll p,ll r=1) { for(;b;b>>=1,a=a*a%p) if(b&1) r=r*a%p;return r; } ll inv(ll x) { return Pow(x,p-2); } void Add(ll &x,ll y) { x=(x+y%p)%p; } void Sub(ll &x,ll y) { x=(x-y%p+p)%p; } void Mul(ll &x,ll y) { x=x*(y%p)%p; } int chkmax(ll &x,ll y) { return x<y?x=y,1:0; } int chkmin(ll &x,ll y) { return x>y?x=y,1:0; } inline ll in(ll x=0,char ch=getchar(),int v=1) { while(ch>'9' || ch<'0') v=ch=='-'?-1:v,ch=getchar(); while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar(); return x*v; } /*end*/ namespace Treap { int cp,rt; int sz[N],ss[N],ch[N][2],f[N],rv[N]; int val[N]; int Newnode(int v) { ++cp,ss[cp]=sz[cp]=1,f[cp]=lc(cp)=rc(cp)=0,val[cp]=v,rv[cp]=rand(); return cp; } void init() { rt=0,rv[0]=-oo; } void Update(int o) { sz[o]=sz[lc(o)]+sz[rc(o)]+ss[o]; } void Rot(int &o,int d) { int t=ch[o][d];ch[o][d]=ch[t][d^1],ch[t][d^1]=o,Update(o),Update(t),o=t; } void insert(int &o,int v) { if(!o) { o=Newnode(v);return; } if(val[o]==v) { ss[o]++,Update(o);return; } int d=v>val[o]; insert(ch[o][d],v); if(rv[ch[o][d]]>rv[o]) Rot(o,d); else Update(o); } void earse(int &o,int v) { if(val[o]==v) { if(ss[o]>1) { ss[o]--,Update(o);return; } int d=rv[lc(o)]<rv[rc(o)]; if(!ch[o][d]) { o=0;return; } Rot(o,d),earse(ch[o][d^1],v); }else earse(ch[o][v>val[o]],v); Update(o); } int rk(int o,int v) { if(val[o]<v) return sz[lc(o)]+ss[o]+rk(rc(o),v); else if(val[o]>v) return rk(lc(o),v); else return sz[lc(o)]; } int kth(int o,int k) { if(sz[lc(o)]>=k) return kth(lc(o),k); else if(sz[lc(o)]+ss[o]<k) return kth(rc(o),k-sz[lc(o)]-ss[o]); else return val[o]; } int pre(int o,int v) { if(!o) return -oo; if(val[o]>=v) return pre(lc(o),v); else return max(val[o],pre(rc(o),v)); } int nxt(int o,int v) { if(!o) return oo; if(val[o]<=v) return nxt(rc(o),v); else return min(val[o],nxt(lc(o),v)); } void insert(int v) { insert(rt,v); } void earse(int v) { earse(rt,v); } int rk(int v) { return rk(rt,v); } int kth(int k) { return kth(rt,k); } int pre(int v) { return pre(rt,v); } int nxt(int v) { return nxt(rt,v); } }; int main() { Treap::init(); for(int T=in();T--;) { int opt=in(),x=in(); switch(opt) { case 1:Treap::insert(x);break; case 2:Treap::earse(x);break; case 3:printf("%d\n",Treap::rk(x)+1);break; case 4:printf("%d\n",Treap::kth(x));break; case 5:printf("%d\n",Treap::pre(x));break; case 6:printf("%d\n",Treap::nxt(x));break; } } return 0; }
- Splay \(O(n\log n)\)
#include <bits/stdc++.h> using namespace std; typedef long long LL; const int N = 200050; inline LL in(LL x=0,char ch=getchar(),int v=1) { while(ch>'9' || ch<'0') v=ch=='-'?-1:v,ch=getchar(); while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar(); return x*v; } int n,q,nw; LL a[N]; struct SplayTree { #define lc(o) ch[o][0] #define rc(o) ch[o][1] #define mid ((l+r)>>1) int cp,rt; LL sum[N],v[N],d[N],rev[N],sz[N],f[N],ch[N][2]; int NewNode() { ++cp; sum[cp]=v[cp]=d[cp]=rev[cp]=lc(cp)=rc(cp)=0; sz[cp]=1; return cp; } void Update(int o) { if(!o) return; sz[o]=sz[lc(o)]+sz[rc(o)]+1; sum[o]=sum[lc(o)]+sum[rc(o)]+v[o]+d[o]*sz[o]; } void Push(int o) { if(!o) return; Push(f[o]); if(rev[o]) { swap(lc(o),rc(o)); if(lc(o)) rev[lc(o)]^=1; if(rc(o)) rev[rc(o)]^=1; rev[o]=0; } if(d[o]) { if(lc(o)) d[lc(o)]+=d[o]; if(rc(o)) d[rc(o)]+=d[o]; v[o]+=d[o],d[o]=0; }Update(lc(o)),Update(rc(o)),Update(o); } void Pushdown(int o) { if(!o) return; if(rev[o]) { swap(lc(o),rc(o)); if(lc(o)) rev[lc(o)]^=1; if(rc(o)) rev[rc(o)]^=1; rev[o]=0; } if(d[o]) { if(lc(o)) d[lc(o)]+=d[o]; if(rc(o)) d[rc(o)]+=d[o]; v[o]+=d[o],d[o]=0; }Update(lc(o)),Update(rc(o)),Update(o); } int Build(int l,int r) { if(l>r){ return 0; } int o=NewNode(); lc(o)=Build(l,mid-1); v[o]=a[nw++]; rc(o)=Build(mid+1,r); if(lc(o)) f[lc(o)]=o; if(rc(o)) f[rc(o)]=o; Update(o); return o; } void Build(int n) { rt=Build(1,n+2); } void Rot(int o) { int p=f[o],k=f[p],r=rc(p)==o; // Pushdown(k),Pushdown(p),Pushdown(o); if(k) ch[k][rc(k)==p]=o; f[p]=o,f[ch[o][r^1]]=p,f[o]=k; ch[p][r]=ch[o][r^1],ch[o][r^1]=p; Update(p),Update(o),Update(k); } void Splay(int o,int ff) { Push(o); for(;f[o]!=ff;) { int p=f[o],k=f[p]; if(k!=ff) Rot((rc(k)==p)==(rc(p)==o)?p:o); Rot(o); } Update(o); if(!ff) rt=o; } int Kth(int o,int k) { Pushdown(o); if(sz[lc(o)]>=k) return Kth(lc(o),k); else if(sz[lc(o)]+1==k) return o; else return Kth(rc(o),k-sz[lc(o)]-1); } LL Kthw(int o,int k) { Pushdown(o); if(sz[lc(o)]>=k) return Kthw(lc(o),k)+d[o]; else if(sz[lc(o)]+1==k) return v[o]+d[o]; else return Kthw(rc(o),k-sz[lc(o)]-1)+d[o]; } LL Kthw(int k) { return Kthw(rt,k+1); } void Add(int l,int r,LL w) { l++,r++; int L=Kth(rt,l-1),R=Kth(rt,r+1); Splay(L,0),Splay(R,L); d[lc(R)]+=w; Update(lc(R)),Update(R),Update(L); } void Insert(int x,LL w) { x++; int L=Kth(rt,x),R=Kth(rt,x+1); Splay(L,0),Splay(R,L); int np=NewNode();lc(R)=np,v[np]=w,f[np]=R; Update(np),Update(R),Update(L); } void Del(int l,int r) { l++,r++; int L=Kth(rt,l-1),R=Kth(rt,r+1); Splay(L,0),Splay(R,L); lc(R)=0,Update(R),Update(L); } LL Qur(int l,int r) { l++,r++; int L=Kth(rt,l-1),R=Kth(rt,r+1); Splay(L,0),Splay(R,L); return sum[lc(R)]; } void Rev(int l,int r) { l++,r++; int L=Kth(rt,l-1),R=Kth(rt,r+1); Splay(L,0),Splay(R,L); rev[lc(R)]^=1; } }py; int main() { n=in(); for(int i=1;i<=n;i++) a[i]=in(); py.Build(n); char opt[20]; int l,r,k,x,v; for(q=in();q--;) { scanf("%s",opt); if(opt[0]=='A') l=in(),r=in(),v=in(),py.Add(l,r,v); if(opt[0]=='I') x=in(),v=in(),py.Insert(x,v); if(opt[0]=='D') l=in(),r=in(),py.Del(l,r); if(opt[0]=='Q') l=in(),r=in(),printf("%lld\n",py.Qur(l,r)); if(opt[0]=='K') k=in(),printf("%lld\n",py.Kthw(k)); if(opt[0]=='R') l=in(),r=in(),py.Rev(l,r); } return 0; }