• 个人简介

    战火不停,征战不止

    newoj:hjz888

    生日礼物链接: look

    #include <bits/stdc++.h>
    #define debug(a) cout<<#a<<"="<<a<<"\n";
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    using namespace std;
    const long long N=2e5+7;
    int main(){
    	return 0;
    }
    
    模板
    函数C总集

    函数C

    long long C(long long n,long long m){
    	long long s=1,a=n,b=1;
    	rep(i,1,m){
    		s=s*a/b;
    		a--;
    		b++;
    	}
    	return s;
    }
    

    (函数C组合式)

    long long qupow(long long a,long long b,long long p){
    	long long s=1;
    	a%=p;
    	while(b){
    		if(b%2==1) s=(a*s)%p;
    		a*=a;
    		b>>=1;
    		a%=p;
    	}
    	return s;
    }
    long long add(long long n,long long mod){
    	long long s=1;
    	rep(i,1,n) s=s*i%mod;
    	return s;
    }
    long long C(long long n,long long m){
    	return add(n,M)*qupow(add(m,M),M-2,M)%M*qupow(add(n-m,M),M-2,M)%M;
    }
    

    (函数C组合式plus+线性乘法逆元+lucas)

    long long qupow(long long a,long long b,long long p){
    	long long s=1;
    	a%=p;
    	while(b){
    		if(b%2==1) s=(a*s)%p;
    		a*=a;
    		b>>=1;
    		a%=p;
    	}
    	return s;
    }
    void init(){
    	fac[0]=inv[0]=1;
    	rep(i,1,p-1) fac[i]=fac[i-1]*i%p;
    	inv[p-1]=qupow(fac[p-1],p-2,p);
    	for(int i=p-2;i;--i) inv[i]=inv[i+1]*(i+1)%p;
    }
    long long C(long long n,long long m){
    	if(m>n) return 0;
    	return fac[n]*inv[m]%p*inv[n-m]%p;
    }
    long long lucas(long long n,long long m){
    	long long ans=1;
    	for(;m;n/=p,m/=p){
    		ans=ans*C(n%p,m%p)%p;
    	}
    	return ans;
    }
    
    线段树+主席树+树链剖分+平衡树总集
    线段树+主席树总集
    李超线段树

    李超线段树(取min)

    struct Tree{
    	int id,k,b;
    	int lson,rson;
    };
    Tree s[N];
    int F(int x,int k,int b){
    	return k*x+b;
    }
    int find(int x,int l,int r,int xx){
    	if(!x) return 1e18;
    	int mid=(l+r)/2,mii=1e18;
    	if(s[x].id!=0) mii=F(xx,s[x].k,s[x].b);
    	if(l==r){
    		return mii;
    	}
    	if(mid>=xx){
    		mii=min(mii,find(s[x].lson,l,mid,xx));
    	}
    	else{
    		mii=min(mii,find(s[x].rson,mid+1,r,xx));
    	}
    	return mii;
    }
    void pd(int &x,int l,int r,int k,int b,int id){
    	int mid=(l+r)/2;
    	if(!x) x=(++cnt);
    	if(s[x].id==0){
    		s[x].id=id;
    		s[x].k=k;
    		s[x].b=b;
    		return;
    	}
    	if(l==r){
    		if(F(l,k,b)<F(l,s[x].k,s[x].b)){
    			s[x].id=id;
    			s[x].k=k;
    			s[x].b=b;
    		}
    		return;
    	}
    	if(F(l,k,b)<F(l,s[x].k,s[x].b)&&F(r,k,b)<F(r,s[x].k,s[x].b)){
    		s[x].id=id;
    		s[x].k=k;
    		s[x].b=b;
    		return;
    	}
    	if(F(l,k,b)>=F(l,s[x].k,s[x].b)&&F(r,k,b)>=F(r,s[x].k,s[x].b)){
    		return;
    	}
    	if(k<s[x].k){
    		if(F(mid,k,b)<F(mid,s[x].k,s[x].b)){
    			pd(s[x].lson,l,mid,s[x].k,s[x].b,s[x].id);
    			s[x].id=id;
    			s[x].k=k;
    			s[x].b=b;
    			return;
    		}
    		else{
    			pd(s[x].rson,mid+1,r,k,b,id);
    			return;
    		}
    	}
    	else{
    		if(F(mid,k,b)<F(mid,s[x].k,s[x].b)){
    			pd(s[x].rson,mid+1,r,s[x].k,s[x].b,s[x].id);
    			s[x].id=id;
    			s[x].k=k;
    			s[x].b=b;
    			return;
    		}
    		else{
    			pd(s[x].lson,l,mid,k,b,id);
    			return;
    		}
    	}
    	return;
    }
    

    李超线段树(取max)

    struct Tree{
    	int id,k,b;
    	int lson,rson;
    };
    Tree s[N];
    int F(int x,int k,int b){
    	return k*x+b;
    }
    int find(int x,int l,int r,int xx){
    	if(!x) return -1e18;
    	int mid=(l+r)/2,maa=-1e18;
    	if(s[x].id!=0) maa=F(xx,s[x].k,s[x].b);
    	if(l==r){
    		return maa;
    	}
    	if(mid>=xx){
    		maa=max(maa,find(s[x].lson,l,mid,xx));
    	}
    	else{
    		maa=max(maa,find(s[x].rson,mid+1,r,xx));
    	}
    	return maa;
    }
    void pd(int &x,int l,int r,int k,int b,int id){
    	int mid=(l+r)/2;
    	if(!x) x=(++cnt);
    	if(s[x].id==0){
    		s[x].id=id;
    		s[x].k=k;
    		s[x].b=b;
    		return;
    	}
    	if(l==r){
    		if(F(l,k,b)>F(l,s[x].k,s[x].b)){
    			s[x].id=id;
    			s[x].k=k;
    			s[x].b=b;
    		}
    		return;
    	}
    	if(F(l,k,b)>F(l,s[x].k,s[x].b)&&F(r,k,b)>F(r,s[x].k,s[x].b)){
    		s[x].id=id;
    		s[x].k=k;
    		s[x].b=b;
    		return;
    	}
    	if(F(l,k,b)<=F(l,s[x].k,s[x].b)&&F(r,k,b)<=F(r,s[x].k,s[x].b)){
    		return;
    	}
    	if(k<s[x].k){
    		if(F(mid,k,b)>F(mid,s[x].k,s[x].b)){
    			pd(s[x].rson,mid+1,r,s[x].k,s[x].b,s[x].id);
    			s[x].id=id;
    			s[x].k=k;
    			s[x].b=b;
    			return;
    		}
    		else{
    			pd(s[x].lson,l,mid,k,b,id);
    			return;
    		}
    	}
    	else{
    		if(F(mid,k,b)>F(mid,s[x].k,s[x].b)){
    			pd(s[x].lson,l,mid,s[x].k,s[x].b,s[x].id);
    			s[x].id=id;
    			s[x].k=k;
    			s[x].b=b;
    			return;
    		}
    		else{
    			pd(s[x].rson,mid+1,r,k,b,id);
    			return;
    		}
    	}
    	return;
    }
    

    线段树(求和+单点改值)

    #include <bits/stdc++.h>
    #define debug(a) cout<<#a<<"="<<a<<"\n";
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    using namespace std;
    const long long N=4e5+7;
    long long a[N],s[N],n,m;
    void add(long long x,long long l,long long r){
    	if(l==r){
    		s[x]=a[l];
    		return;
    	}
    	long long mid=(l+r)/2;
    	add(x*2,l,mid);
    	add(x*2+1,mid+1,r);
    	s[x]=s[x*2]+s[x*2+1];
    }
    int find(long long x,long long l,long long r,long long xx,long long yy){
    	if(xx<=l&&r<=yy){
    		return s[x];
    	}
    	long long mid=(l+r)/2,sum=0;
    	if(mid>=xx){
    		sum+=find(x*2,l,mid,xx,yy);
    	}
    	if(mid+1<=yy){
    		sum+=find(x*2+1,mid+1,r,xx,yy);
    	}
    	return sum;
    }
    void adg1(long long x,long long l,long long r,long long xx,long long yy){
    	if(l==r){
    		s[x]+=yy;
    		return;
    	}
    	long long mid=(l+r)/2;
    	if(mid>=xx){
    		adg1(x*2,l,mid,xx,yy);
    	}
    	else{
    		adg1(x*2+1,mid+1,r,xx,yy);
    	}
    	s[x]=s[x*2]+s[x*2+1];
    }
    int main(){
    	cin>>n>>m;
    	rep(i,1,m){
    		long long x,y,z;
    		cin>>x>>y>>z;
    		if(x==0){
    			adg1(1,1,n,y,z);
    		}
    		else{
    			cout<<find(1,1,n,y,z)<<"\n";
    		}
    	}
    	return 0;
    }
    

    线段树(求和+区间改值+lazy)

    struct Tre{
    	long long s,sum;
    	Tre(long long x=0,long long y=0){s=x,sum=y;}
    	friend Tre operator+(const Tre &a,const Tre &b){
    		Tre sss;
    		sss.s=a.s+b.s;
    		sss.sum=a.sum+b.sum;
    		return sss;
    	}
    };
    class segmenttree{
    	private:
    		struct tre{
    			long long l,r,lson,rson;
    			long long lazy;
    			Tre s;
    		};
    		vector<tre> tre;
    		void init(int x,int l,int r){
    			tre[x].l=l,tre[x].r=r,tre[x].lazy=tre[x].lson=tre[x].rson=0;
    			tre[x].s.s=tre[x].s.sum=0;
    		}
    		void pu(int x){
    			tre[x].s=tre[tre[x].lson].s+tre[tre[x].rson].s;
    		}
    		void pt(long long x,long long y){
    			tre[x].s.s+=(tre[x].r-tre[x].l+1);
    			tre[x].s.sum+=y*(tre[x].r-tre[x].l+1);
    			tre[x].lazy+=y;
    		}
    		void pd(long long x){
    			pt(tre[x].lson,tre[x].lazy),pt(tre[x].rson,tre[x].lazy),tre[x].lazy=0;
    		}
    	public:
    		void add(int x,int l,int r){
    			init(x,l,r);
    			if(l==r) return;
    			int mid=(l+r)/2;
    			tre[x].lson=x*2,add(x*2,l,mid);
    			tre[x].rson=x*2+1,add(x*2+1,mid+1,r);
    			pu(x);
    		}
    		segmenttree(long long x){
    			tre.resize(x*4+1),add(1,1,x);
    		}
    		void adg2(long long x,long long l,long long r,long long xx,long long yy,long long p){
    			if(xx<=l&&r<=yy){
    				pt(x,p);
    				return;
    			}
    			if(tre[x].lazy) pd(x);
    			long long mid=(l+r)/2;
    			if(mid>=xx) adg2(x*2,l,mid,xx,yy,p);
    			if(mid+1<=yy) adg2(x*2+1,mid+1,r,xx,yy,p);
    			pu(x);
    		}
    		Tre find(long long x,long long l,long long r,long long xx,long long yy){
    			if(xx<=l&&r<=yy) return tre[x].s;
    			long long mid=(l+r)/2;
    			if(tre[x].lazy) pd(x);
    			Tre sum;
    			if(mid>=xx) sum=sum+find(x*2,l,mid,xx,yy);
    			if(mid+1<=yy) sum=sum+find(x*2+1,mid+1,r,xx,yy);
    			return sum;
    		}
    };
    

    权值线段树(求和+单点改值+动态开点)

    #include <bits/stdc++.h>
    #define debug(a) cout<<#a<<"="<<a<<"\n";
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    using namespace std;
    const long long N=1e7+7;
    long long a[N],s[N],lson[N],rson[N],tre,cnt,n,ans;
    long long find(long long x,long long l,long long r,long long xx,long long yy){
    	if(x==0) return 0;
    	if(xx<=l&&r<=yy){
    		return s[x];
    	}
    	long long mid=(l+r)/2,sum=0;
    	if(mid>=xx){
    		sum+=find(lson[x],l,mid,xx,yy);
    	}
    	if(mid+1<=yy){
    		sum+=find(rson[x],mid+1,r,xx,yy);
    	}
    	return sum;
    }
    void adg1(long long &x,long long l,long long r,long long xx,long long yy){
    	if(x==0) x=++cnt;
    	if(l==r){
    		s[x]+=yy;
    		return;
    	}
    	long long mid=(l+r)/2;
    	if(mid>=xx){
    		adg1(lson[x],l,mid,xx,yy);
    	}
    	else{
    		adg1(rson[x],mid+1,r,xx,yy);
    	}
    	s[x]=s[lson[x]]+s[rson[x]];
    }
    int main(){
    	cin>>n;
    	rep(i,1,n){
    		long long x;
    		cin>>x;
    		ans+=find(tre,1,1e9,x+1,1e9);
    		adg1(tre,1,1e9,x,1);
    	}
    	cout<<ans;
    	return 0;
    }
    

    线段树(求和+区间改值+lazy+标记永久化)

    #include <bits/stdc++.h>
    #define debug(a) cout<<#a<<"="<<a<<"\n";
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    using namespace std;
    const long long N=4e6+7;
    long long a[N],mi[N],lazy[N],n,m,ans;
    void add(long long x,long long l,long long r){
    	if(l==r){
    		mi[x]=a[l];
    		return;
    	}
    	long long mid=(l+r)/2;
    	add(x*2,l,mid);
    	add(x*2+1,mid+1,r);
    	mi[x]=min(mi[x*2],mi[x*2+1]);
    }
    long long find(long long x,long long l,long long r,long long xx,long long yy){
    	if(xx<=l&&r<=yy){
    		return mi[x];
    	}
    	long long mid=(l+r)/2,mii=1e18;
    	if(mid>=xx){
    		mii=min(mii,find(x*2,l,mid,xx,yy));
    	}
    	if(mid+1<=yy){
    		mii=min(mii,find(x*2+1,mid+1,r,xx,yy));
    	}
    	return mii+lazy[x];
    }
    void adg2(long long x,long long l,long long r,long long xx,long long yy,long long p){
    	if(xx<=l&&r<=yy){
    		lazy[x]+=p;
    		mi[x]+=p;
    		return;
    	}
    	long long mid=(l+r)/2;
    	if(mid>=xx){
    		adg2(x*2,l,mid,xx,yy,p);
    	}
    	if(mid+1<=yy){
    		adg2(x*2+1,mid+1,r,xx,yy,p);
    	}
    	mi[x]=min(mi[x*2],mi[x*2+1])+lazy[x];
    }
    int main(){
    	cin>>n>>m;
    	rep(i,1,n){
    		cin>>a[i];
    	}
    	add(1,1,n);
    	rep(i,1,m){
    		long long l,r,p;
    		cin>>p>>l>>r;
    		ans=find(1,1,n,l,r);
    		if(ans<p){
    			cout<<-1<<"\n"<<i;
    			return 0;
    		}
    		adg2(1,1,n,l,r,-p);
    	}
    	cout<<0;
    	return 0;
    }
    

    主席树(可持久化线段树)

    #include <bits/stdc++.h>
    #define debug(a) cout<<#a<<"="<<a<<"\n";
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    using namespace std;
    const long long N=1e7+7;
    long long a[N],b[N],s[N],lson[N],rson[N],n,m,tre[N],cnt,ans,t;
    long long finds(long long x,long long y,long long l,long long r,long long xx){
    	if(l==r){
    		return l;
    	}
    	long long mid=(l+r)/2;
    	if(s[lson[y]]-s[lson[x]]>=xx){
    		return finds(lson[x],lson[y],l,mid,xx);
    	}
    	else{
    		return finds(rson[x],rson[y],mid+1,r,xx-(s[lson[y]]-s[lson[x]]));
    	}
    }
    void add(long long &x,long long l,long long r){
    	x=++cnt;
    	if(l==r){
    		s[x]=0;
    		return;
    	}
    	long long mid=(l+r)/2;
    	add(lson[x],l,mid);
    	add(rson[x],mid+1,r);
    }
    long long adg1(long long ol,long long l,long long r,long long xx){
    	long long x=++cnt;
    	lson[x]=lson[ol];
    	rson[x]=rson[ol];
    	s[x]=s[ol]+1;
    	if(l==r) return x;
    	long long mid=(l+r)/2;
    	if(mid>=xx){
    		lson[x]=adg1(lson[x],l,mid,xx);
    	}
    	else{
    		rson[x]=adg1(rson[x],mid+1,r,xx);
    	}
    	return x;
    }
    int main(){
    	cin>>n>>m;
    	rep(i,1,n){
    		cin>>a[i];
    		b[i]=a[i];
    	}
    	sort(b+1,b+1+n);
    	t=unique(b+1,b+1+n)-b-1;
    	add(tre[0],1,t);
    	rep(i,1,n){
    		long long x=lower_bound(b+1,b+1+t,a[i])-b;
    		tre[i]=adg1(tre[i-1],1,t,x);
    	}
    	rep(i,1,m){
    		long long l,r,k;
    		cin>>l>>r>>k;
    		cout<<b[finds(tre[l-1],tre[r],1,t,k)]<<"\n";
    	}
    	return 0;
    }
    

    线段树(加乘混合+区间改值+求和+lazy)

    #include <bits/stdc++.h>
    #define debug(a) cout<<#a<<"="<<a<<"\n";
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    using namespace std;
    const long long N=4e6+7,M=1e9+7;
    long long a[N],b[N],s[N],lazy[N],lazy2[N],n,m,k,ans;
    long long qupow(long long a,long long b,long long p){
    	long long s=1;
    	a%=p;
    	while(b){
    		if(b%2==1) s=(a*s)%p;
    		a*=a;
    		b>>=1;
    		a%=p;
    	}
    	return s;
    }
    void pt(long long x,long long l,long long r,long long p,long long y){
    	s[x]=(s[x]*y%M+(p*(r-l+1)%M))%M;
    	lazy[x]=(lazy[x]*y%M+p)%M;
    	lazy2[x]=(lazy2[x]*y%M)%M;
    }
    void pd(long long x,long long l,long long r){
    	long long mid=(l+r)/2;
    	pt(x*2,l,mid,lazy[x],lazy2[x]);
    	pt(x*2+1,mid+1,r,lazy[x],lazy2[x]);
    	lazy[x]=0;
    	lazy2[x]=1;
    }
    void add(long long x,long long l,long long r){
    	lazy2[x]=1;
    	if(l==r){
    		s[x]=a[l];
    		return;
    	}
    	long long mid=(l+r)/2;
    	add(x*2,l,mid);
    	add(x*2+1,mid+1,r);
    	s[x]=(s[x*2]+s[x*2+1])%M;
    }
    long long find(long long x,long long l,long long r,long long xx,long long yy){
    	if(xx<=l&&r<=yy){
    		return s[x];
    	}
    	pd(x,l,r);
    	long long mid=(l+r)/2,sum=0;
    	if(mid>=xx){
    		sum+=find(x*2,l,mid,xx,yy);
    	}
    	if(mid+1<=yy){
    		sum+=find(x*2+1,mid+1,r,xx,yy);
    	}
    	sum%=M;
    	return sum;
    }
    void adg2(long long x,long long l,long long r,long long xx,long long yy,long long p,long long y){
    	if(xx<=l&&r<=yy){
    		if(p==1){
    			lazy[x]=(lazy[x]+y)%M;
    			s[x]=(s[x]+y*(r-l+1)%M)%M;
    		}
    		if(p==2){
    			lazy[x]=(lazy[x]*y)%M;
    			lazy2[x]=(lazy2[x]*y)%M;
    			s[x]=(s[x]*y)%M;
    		}
    		return;
    	}
    	pd(x,l,r);
    	long long mid=(l+r)/2;
    	if(mid>=xx){
    		adg2(x*2,l,mid,xx,yy,p,y);
    	}
    	if(mid+1<=yy){
    		adg2(x*2+1,mid+1,r,xx,yy,p,y);
    	}
    	s[x]=(s[x*2]+s[x*2+1])%M;
    }
    int main(){
    	cin>>n>>m;
    	rep(i,1,n){
    		cin>>a[i];
    	}
    	add(1,1,n);
    	rep(i,1,m){
    		long long p,x,y,z;
    		cin>>p;
    		if(p==1){
    			cin>>x>>y>>z;
    			adg2(1,1,n,x,y,1,z);
    		}
    		if(p==2){
    			cin>>x>>y>>z;
    			adg2(1,1,n,x,y,2,z);
    		}
    		if(p==3){
    			cin>>x>>y;
    			cout<<qupow(find(1,1,n,x,x),y,M)<<"\n";
    		}
    	}
    	return 0;
    }
    

    线段树合并(求第k大+单点改值+动态开点)

    #include <bits/stdc++.h>
    #define debug(a) cout<<#a<<"="<<a<<"\n";
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    using namespace std;
    const int N=1e7+7;
    int a[N],s[N],lson[N],rson[N],ff[N],tre,cnt,n,m,k;
    int find(int x){
    	if(a[x]!=x) a[x]=find(a[x]);
    	return a[x];
    }
    void adg1(int &x,int l,int r,int xx,int yy){
    	if(x==0) x=++cnt;
    	if(l==r){
    		s[x]=1;
    		ff[x]=yy;
    		return;
    	}
    	int mid=(l+r)/2;
    	if(mid>=xx){
    		adg1(lson[x],l,mid,xx,yy);
    	}
    	else{
    		adg1(rson[x],mid+1,r,xx,yy);
    	}
    	s[x]=s[lson[x]]+s[rson[x]];
    	if(rson[x]) ff[x]=ff[rson[x]];
    	else ff[x]=ff[lson[x]];
    }
    int merge(int x,int y){
    	if(x==y) return x;
    	if(!x||!y) return x|y;
    	s[x]+=s[y];
    	lson[x]=merge(lson[x],lson[y]);
    	rson[x]=merge(rson[x],rson[y]);
    	if(rson[x]) ff[x]=ff[rson[x]];
    	else ff[x]=ff[lson[x]];
    	return x;
    }
    int finds(int x,int y){
    	if(y>s[x]) return -1;
    	if(s[x]==y) return ff[x];
    	if(s[lson[x]]>=y){
    		return finds(lson[x],y);
    	}
    	else{
    		return finds(rson[x],y-s[lson[x]]);
    	}
    }
    int main(){
    	cin>>n>>m;
    	cnt=n;
    	rep(i,1,n){
    		int x;
    		cin>>x;
    		a[i]=i;
    		adg1(i,1,n,x,i);
    	}
    	rep(i,1,m){
    		int u,v;
    		cin>>u>>v;
    		int p=find(u),q=find(v);
    		if(p!=q){
    			a[p]=a[q]=merge(p,q);
    		}
    	}
    	cin>>k;
    	rep(i,1,k){
    		char c;
    		int x,y;
    		cin>>c;
    		if(c=='B'){
    			cin>>x>>y;
    			int p=find(x),q=find(y);
    			if(p!=q){
    				a[p]=a[q]=merge(p,q);
    			}
    		}
    		if(c=='Q'){
    			cin>>x>>y;
    			int p=find(x);
    			cout<<finds(p,y)<<"\n";
    		}
    	}
    	return 0;
    }
    
    树链剖分

    树链剖分(重链剖分+线段树,适用于查区间和、最值)

    #include <bits/stdc++.h>
    #define debug(a) cout<<#a<<"="<<a<<"\n";
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    using namespace std;
    const long long N=8e5+7,M=2e5+7;
    long long a[M],s[N],ma[N],f[M],dfn[M],dff[M],siz[M],son[M],top[M],h[M],n,m,cnt;
    vector<int> g[M];
    string c;
    void dfs(int x,int fa){
    	siz[x]=1;
    	h[x]=h[fa]+1;
    	f[x]=fa;
    	for(int i=0;i<g[x].size();i++){
    		int j=g[x][i];
    		if(f[x]!=j){
    			dfs(j,x);
    			siz[x]+=siz[j];
    			if(siz[son[x]]<siz[j]){
    				son[x]=j;
    			}
    		}
    	}
    }
    void dfs2(int x,int fa){
    	top[x]=fa;
    	dfn[x]=++cnt;
    	dff[cnt]=x;
    	if(!son[x]){
    		return;
    	}
    	dfs2(son[x],fa);
    	for(int i=0;i<g[x].size();i++){
    		int j=g[x][i];
    		if(f[x]!=j&&j!=son[x]){
    			dfs2(j,j);
    		}
    	}
    }
    void pt(long long x,long long y){
    	s[x]=y;
    	ma[x]=y;
    }
    void add(long long x,long long l,long long r){
    	if(l==r){
    		ma[x]=s[x]=a[dff[l]];
    		return;
    	}
    	long long mid=(l+r)/2;
    	add(x*2,l,mid);
    	add(x*2+1,mid+1,r);
    	ma[x]=max(ma[x*2],ma[x*2+1]);
    	s[x]=s[x*2]+s[x*2+1];
    }
    long long finds(long long x,long long l,long long r,long long xx,long long yy){
    	if(xx<=l&&r<=yy){
    		return s[x];
    	}
    	long long mid=(l+r)/2,sum=0;
    	if(mid>=xx){
    		sum+=finds(x*2,l,mid,xx,yy);
    	}
    	if(mid+1<=yy){
    		sum+=finds(x*2+1,mid+1,r,xx,yy);
    	}
    	return sum;
    }
    long long finds2(long long x,long long l,long long r,long long xx,long long yy){
    	if(xx<=l&&r<=yy){
    		return ma[x];
    	}
    	long long mid=(l+r)/2,maa=-1e18;
    	if(mid>=xx){
    		maa=max(maa,finds2(x*2,l,mid,xx,yy));
    	}
    	if(mid+1<=yy){
    		maa=max(maa,finds2(x*2+1,mid+1,r,xx,yy));
    	}
    	return maa;
    }
    void adg2(long long x,long long l,long long r,long long xx,long long yy,long long p){
    	if(xx<=l&&r<=yy){
    		pt(x,p);
    		return;
    	}
    	long long mid=(l+r)/2;
    	if(mid>=xx){
    		adg2(x*2,l,mid,xx,yy,p);
    	}
    	if(mid+1<=yy){
    		adg2(x*2+1,mid+1,r,xx,yy,p);
    	}
    	ma[x]=max(ma[x*2],ma[x*2+1]);
    	s[x]=s[x*2]+s[x*2+1];
    }
    long long maxx(long long x,long long y){
    	long long ans=-1e18;
    	while(top[x]!=top[y]){
    		if(h[top[x]]<h[top[y]]){
    			swap(x,y);
    		}
    		ans=max(ans,finds2(1,1,n,dfn[top[x]],dfn[x]));
    		x=f[top[x]];
    	}
    	if(h[x]<h[y]){
    		swap(x,y);
    	}
    	ans=max(ans,finds2(1,1,n,dfn[y],dfn[x]));
    	return ans;
    }
    long long summ(long long x,long long y){
    	long long ans=0;
    	while(top[x]!=top[y]){
    		if(h[top[x]]<h[top[y]]){
    			swap(x,y);
    		}
    		ans+=finds(1,1,n,dfn[top[x]],dfn[x]);
    		x=f[top[x]];
    	}
    	if(h[x]<h[y]){
    		swap(x,y);
    	}
    	ans+=finds(1,1,n,dfn[y],dfn[x]);
    	return ans;
    }
    int main(){
    	cin>>n;
    	rep(i,1,n-1){
    		int u,v;
    		cin>>u>>v;
    		g[u].push_back(v);
    		g[v].push_back(u);
    	}
    	dfs(1,0);
    	dfs2(1,1);
    	rep(i,1,n){
    		cin>>a[i];
    	}
    	add(1,1,n);
    	cin>>m;
    	rep(i,1,m){
    		long long x,y;
    		cin>>c>>x>>y;
    		if(c=="CHANGE"){
    			adg2(1,1,n,dfn[x],dfn[x],y);
    		}
    		if(c=="QMAX"){
    			cout<<maxx(x,y)<<"\n";
    		}
    		if(c=="QSUM"){
    			cout<<summ(x,y)<<"\n";
    		}
    	}
    	return 0;
    }
    
    平衡树总集

    平衡树

    class treap{
    	private:
    		long long rnd(){
    			long long MMM=1e9+7;
    			return rand()%MMM;
    		}
    		struct tre{
    			long long lson,rson,s,v,k;
    			long long lazy;
    		};
    		vector<tre> tre;
    		long long tot,root;
    		long long init(long long v){
    			tre[++tot]={0,0,1,v,rnd(),0};
    			return tot;
    		}
    		void pu(long long x){
    			tre[x].s=tre[tre[x].lson].s+tre[tre[x].rson].s+1;
    		}
    		pair<long long,long long> split(long long x,long long k){
    			if(x==0) return make_pair(0,0);
    			if(tre[tre[x].lson].s<k){
    				auto sss=split(tre[x].rson,k-tre[tre[x].lson].s-1);
    				tre[x].rson=sss.first;
    				pu(x);
    				sss.first=x;
    				return sss;
    			}
    			auto sss=split(tre[x].lson,k);
    			tre[x].lson=sss.second;
    			pu(x);
    			sss.second=x;
    			return sss;
    		}
    		pair<long long,long long> split2(long long x,long long v){
    			if(x==0) return make_pair(0,0);
    			if(tre[x].v<v){
    				auto sss=split2(tre[x].rson,v);
    				tre[x].rson=sss.first;
    				pu(x);
    				sss.first=x;
    				return sss;
    			}
    			auto sss=split2(tre[x].lson,v);
    			tre[x].lson=sss.second;
    			pu(x);
    			sss.second=x;
    			return sss;
    		}
    		long long merge(long long x,long long y){
    			if(!x||!y) return x+y;
    			if(tre[x].k>tre[y].k){
    				tre[x].rson=merge(tre[x].rson,y);
    				pu(x);
    				return x;
    			}
    			tre[y].lson=merge(x,tre[y].lson);
    			pu(y);
    			return y;
    		}
    	public:
    		treap(long long x){
    			tre.resize(x+1);
    			tot=root=0;
    		}
    		void put(long long v,long long s){
    			if(s>0){
    				auto [x,y]=split2(root,v);
    				long long z=init(v);
    				rep(i,1,s-1){
    					long long zz=init(v);
    					z=merge(z,zz);
    				}
    				x=merge(x,z);
    				root=merge(x,y);
    			}
    			else{
    				auto [x,y]=split2(root,v);
    				auto [zz,z]=split(y,-s);
    				root=merge(x,z);
    			}
    		}
    		long long rank(long long v){
    			auto [x,y]=split2(root,v);
    			long long ans=tre[x].s+1;
    			root=merge(x,y);
    			return ans;
    		}
    		long long find(long long k){
    			auto [x,y]=split(root,k-1);
    			auto [zz,z]=split(y,1);
    			long long ans=tre[zz].v;
    			y=merge(zz,z);
    			root=merge(x,y);
    			return ans;
    		}
    		long long prev(long long v){
    			return find(rank(v)-1);
    		}
    		long long next(long long v){
    			return find(rank(v+1));
    		}
    };
    

    文艺平衡树

    class arttreap{
    	private:
    		long long rnd(){
    			long long MMM=1e9+7;
    			return rand()%MMM;
    		}
    		struct tre{
    			long long lson,rson,s,v,k,mi;
    			long long lazy;
    		};
    		vector<tre> tre;
    		long long tot;
    		long long init(long long v){
    			tre[++tot]={0,0,1,v,rnd(),v,0};
    			return tot;
    		}
    		void pu(long long x){
    			tre[x].s=tre[tre[x].lson].s+tre[tre[x].rson].s+1;
    			if(!tre[x].lson&&!tre[x].rson) tre[x].mi=tre[x].v;
    			else if(!tre[x].lson||!tre[x].rson) tre[x].mi=min(tre[x].v,tre[tre[x].lson].mi+tre[tre[x].rson].mi);
    			else tre[x].mi=min({tre[x].v,tre[tre[x].lson].mi,tre[tre[x].rson].mi});
    		}
    		void pt(long long x){
    			if(x==0) return;
    			tre[x].lazy^=1;
    			swap(tre[x].lson,tre[x].rson);
    		}
    		void pd(long long x){
    			pt(tre[x].lson),pt(tre[x].rson);tre[x].lazy=0;
    		}
    	public:
    		void print(long long x){
    			if(x==0) return;
    			if(tre[x].lazy) pd(x);
    			print(tre[x].lson);
    			cout<<tre[x].v<<" ";
    			print(tre[x].rson);
    		}
    		pair<long long,long long> split(long long x,long long k){
    			if(x==0) return make_pair(0,0);
    			if(tre[x].lazy) pd(x);
    			if(tre[tre[x].lson].s<k){
    				auto sss=split(tre[x].rson,k-tre[tre[x].lson].s-1);
    				tre[x].rson=sss.first;
    				pu(x);
    				sss.first=x;
    				return sss;
    			}
    			auto sss=split(tre[x].lson,k);
    			tre[x].lson=sss.second;
    			pu(x);
    			sss.second=x;
    			return sss;
    		}
    		pair<long long,long long> split2(long long x,long long v){
    			if(x==0) return make_pair(0,0);
    			if(tre[x].lazy) pd(x);
    			if(tre[x].v<v){
    				auto sss=split2(tre[x].rson,v);
    				tre[x].rson=sss.first;
    				pu(x);
    				sss.first=x;
    				return sss;
    			}
    			auto sss=split2(tre[x].lson,v);
    			tre[x].lson=sss.second;
    			pu(x);
    			sss.second=x;
    			return sss;
    		}
    		long long merge(long long x,long long y){
    			if(!x||!y) return x+y;
    			if(tre[x].lazy) pd(x);
    			if(tre[y].lazy) pd(y);
    			if(tre[x].k>tre[y].k){
    				tre[x].rson=merge(tre[x].rson,y);
    				pu(x);
    				return x;
    			}
    			tre[y].lson=merge(x,tre[y].lson);
    			pu(y);
    			return y;
    		}
    		long long root;
    		arttreap(long long x){
    			tre.resize(x+1);
    			tot=root=0;
    		}
    		void put(long long v,long long s){
    			rep(i,1,s){
    				long long zz=init(v);
    				root=merge(root,zz);
    			}
    		}
    		long long rank(long long x){
    			if(x==0) return 0;
    			if(tre[x].lazy) pd(x);
    			if(tre[x].mi==tre[x].v){
    				return tre[tre[x].lson].s+1;
    			}
    			if(!tre[x].rson) return rank(tre[x].lson);
    			if(!tre[x].lson) return rank(tre[x].rson)+1;
    			if(tre[tre[x].lson].mi==tre[x].mi){
    				return rank(tre[x].lson);
    			}
    			return rank(tre[x].rson)+tre[tre[x].lson].s+1;
    		}
    		void adg(long long l,long long r){
    			auto [x,y]=split(root,l-1);
    			auto [zz,z]=split(y,r-l+1);
    			pt(zz);
    			y=merge(zz,z);
    			root=merge(x,y);
    		}
    };
    
    强连通分量总集

    强连通分量

    void tarjan(long long x){
    	dfn[x]=low[x]=++num;
    	q.push(x);
    	for(long long i=0;i<g[x].size();++i){
    		long long j=g[x][i];
    		if(!dfn[j]){
    			tarjan(j);
    			low[x]=min(low[x],low[j]);
    		}
    		else if(!an[j]) low[x]=min(low[x],dfn[j]);
    	}
    	if(low[x]==dfn[x]){
    		an[x]=++s;
    		ans[s].push_back(x);
    		while(q.size()&&q.top()!=x){
    			ans[s].push_back(q.top());
    			an[q.top()]=s;
    			q.pop();
    		}
    		q.pop();
    	}
    }
    

    找桥(割边)

    #include <bits/stdc++.h>
    #define debug(a) cout<<#a<<"="<<a<<"\n";
    #define rep(i,a,b) for(long long i=a;i<=b;++i)
    using namespace std;
    const long long N=2e5+7;
    long long a[N],p[N],now[N],son[N],an[N],dfn[N],low[N],t=0,n,m,num,ans;
    void put(long long a,long long b){
    	p[++t]=now[a];
    	now[a]=t;
    	son[t]=b;
    }
    void tarjan(long long x,long long in){
    	dfn[x]=low[x]=++num;
    	long long neww=in;
    	if(in&1) neww++;
    	else neww--;
    	for(long long i=now[x];i;i=p[i]){
    		long long j=son[i];
    		if(!dfn[j]){
    			tarjan(j,i);
    			low[x]=min(low[x],low[j]);
    			if(low[j]>dfn[x]){
    				an[i]=1;
    				if(i&1) an[i+1]=1;
    				else an[i-1]=1;
    			}
    		}
    		else if(i!=neww) low[x]=min(low[x],dfn[j]);
    	}
    }
    int main(){
    	cin>>n>>m;
    	rep(i,1,m){
    		long long u,v;
    		cin>>u>>v;
    		put(u,v);
    		put(v,u);
    	}
    	rep(i,1,n) if(!dfn[i]) tarjan(i,0);
    	for(int i=1;i<=t;i+=2){
    		if(an[i]) ans++;
    	}
    	cout<<ans<<"\n";
    	return 0;
    }
    

    割点及点双联通分量

    #include <bits/stdc++.h>
    #define debug(a) cout<<#a<<"="<<a<<"\n";
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    using namespace std;
    const int N=5e5+7;
    int a[N],an[N],dfn[N],low[N],sum[N],t=0,n,m,num,s;
    vector<int> g[N],ans[N];
    stack<int> q;
    void tarjan(int x,int fa,int gen){
    	dfn[x]=low[x]=++num;
    	q.push(x);
    	int flag=0;
    	for(int i=0;i<g[x].size();i++){
    		int j=g[x][i];
    		if(!dfn[j]){
    			tarjan(j,x,gen);
    			low[x]=min(low[x],low[j]);
    			if(low[j]>=dfn[x]){
    				flag++;
    				ans[++s].push_back(x);
    				while(q.size()&&q.top()!=j){
    					ans[s].push_back(q.top());
    					q.pop();
    				}
    				ans[s].push_back(j);
    				q.pop();
    				if(x!=gen||flag>1) an[x]=1;
    			}
    		}
    		else low[x]=min(low[x],dfn[j]);
    	}
    	if(flag==0&&x==gen){
    		ans[++s].push_back(x);
    	}
    }
    int main(){
    	cin>>n>>m;
    	rep(i,1,m){
    		int u,v;
    		cin>>u>>v;
    		g[u].push_back(v);
    		g[v].push_back(u);
    	}
    	rep(i,1,n) if(!dfn[i]) tarjan(i,0,i);
    	int ss=0;
    	rep(i,1,n){
    		if(an[i]) ss++;
    	}
    	cout<<ss<<"\n";
    	rep(i,1,n){
    		if(an[i]) cout<<i<<" ";
    	}
    	return 0;
    }
    

    边双连通分量

    #include <bits/stdc++.h>
    #define debug(a) cout<<#a<<"="<<a<<"\n";
    #define rep(i,a,b) for(long long i=a;i<=b;++i)
    using namespace std;
    const long long N=4e6+7;
    long long p[N],now[N],son[N],an[N],dfn[N],low[N],sum[N],v[N],t=0,n,m,num,s;
    vector<long long> g[N];
    void put(long long a,long long b){
    	p[++t]=now[a];
    	now[a]=t;
    	son[t]=b;
    }
    void tarjan(long long x,long long in){
    	dfn[x]=low[x]=++num;
    	long long neww=in;
    	if(in&1) neww++;
    	else neww--;
    	for(long long i=now[x];i;i=p[i]){
    		long long j=son[i];
    		if(!dfn[j]){
    			tarjan(j,i);
    			low[x]=min(low[x],low[j]);
    			if(low[j]>dfn[x]){
    				an[i]=1;
    				if(i&1) an[i+1]=1;
    				else an[i-1]=1;
    			}
    		}
    		else if(i!=neww) low[x]=min(low[x],dfn[j]);
    	}
    }
    void dfs(long long x,long long u){
    	sum[u]++;
    	v[x]=u;
    	g[u].push_back(x);
    	for(long long i=now[x];i;i=p[i]){
    		long long j=son[i];
    		if(!v[j]&&!an[i]){
    			dfs(j,u);
    		}
    	}
    }
    int main(){
    	cin>>n>>m;
    	rep(i,1,m){
    		long long u,v;
    		cin>>u>>v;
    		put(u,v);
    		put(v,u);
    	}
    	rep(i,1,n) if(!dfn[i]) tarjan(i,0);
    	rep(i,1,n) if(!v[i]) dfs(i,++s);
    	cout<<s<<"\n";
    	rep(i,1,s){
    		cout<<sum[i]<<" ";
    		rep(j,0,g[i].size()-1){
    			cout<<g[i][j]<<" ";
    		}
    		cout<<"\n";
    	}
    	return 0;
    }
    
    字符串&&hash总集

    hash

      #include <bits/stdc++.h>
    #define debug(a) cout<<#a<<"="<<a<<"\n";
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    using namespace std;
    const long long N=1e6+7,M=1e9+7,B=133;
    long long p[N],n,ans,num;
    char c[N];
    map<int,int> q; 
    int main(){
    	p[0]=1;
    	rep(i,1,1e6){
    		p[i]=p[i-1]*B%M;
    	}
    	cin>>n;
    	rep(i,1,n){
    		scanf("%s",c+1);
    		long long l=strlen(c+1);
    		num=0;
    		rep(i,1,l){
    			num=((num*B%M)+(c[i]-'a'+1))%M;
    		}
    		if(q[num]==0) ans++;
    		q[num]=1;
    	}
    	cout<<ans;
    	return 0;
    }
    

    hash字符串

    #include <bits/stdc++.h>
    #define int long long
    #define debug(a) cout<<#a<<"="<<a<<"\n";
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    using namespace std;
    const int N=1e6+7,M=1e9+7,B=19260817;
    int p[N],sum[N],ans;
    string c1,c2;
    int check(int l,int r){
    	return (sum[r]-sum[l-1]*p[r-l+1]%M+M)%M;
    }
    signed main(){
    	cin>>c1>>c2;
    	p[0]=1;
    	rep(i,1,c1.size()){
    		p[i]=p[i-1]*B%M;
    	}
    	rep(i,1,c1.size()){
    		sum[i]=((sum[i-1]*B%M)+(c1[i-1]))%M;
    	}
    	int s=0;
    	rep(i,1,c2.size()){
    		s=((s*B%M)+(c2[i-1]))%M;
    	}
    	rep(i,1,c1.size()-c2.size()+1){
    		if(check(i,i+(c2.size())-1)==s){
    			ans++;
    		}
    	}
    	cout<<ans;
    	return 0;
    }
    

    双hash

    #include <bits/stdc++.h>
    #define debug(a) cout<<#a<<"="<<a<<"\n";
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    using namespace std;
    const long long N=1e6+7,M=1e9+7,B1=133,B2=133;
    long long p1[N],p2[N],sum1[N],sum2[N],n,ans,num;
    char c[N];
    bool check1(long long l1,long long r1,long long l2,long long r2){
    	long long l=r1-l1+1;
    	return (((sum1[r1]-sum1[l1-1]*p1[l]%M)+M)%M)==(((sum1[r2]-sum1[l2-1]*p1[l]%M)+M)%M);
    }
    bool check2(long long l1,long long r1,long long l2,long long r2){
    	long long l=r1-l1+1;
    	return (((sum2[r1]-sum2[l1-1]*p2[l]%M)+M)%M)==(((sum2[r2]-sum2[l2-1]*p2[l]%M)+M)%M);
    }
    int main(){
    	scanf("%s",c+1);
    	long long l=strlen(c+1);
    	p1[0]=p2[0]=sum1[0]=sum2[0]=1;
    	rep(i,1,l){
    		p1[i]=p1[i-1]*B1%M;
    	}
    	rep(i,1,l){
    		p2[i]=p2[i-1]*B2%M;
    	}
    	rep(i,1,l){
    		sum1[i]=((sum1[i-1]*B1%M)+(c[i]-'a'+1))%M;
    	}
    	rep(i,1,l){
    		sum2[i]=((sum2[i-1]*B2%M)+(c[i]-'a'+1))%M;
    	}
    	cin>>n;
    	rep(i,1,n){
    		long long l1,r1,l2,r2;
    		scanf("%lld%lld%lld%lld",&l1,&r1,&l2,&r2);
    		if(r1-l1!=r2-l2){
    			cout<<"No\n";
    			continue;
    		}
    		if(check1(l1,r1,l2,r2)&&check1(l1,r1,l2,r2)) cout<<"Yes\n";
    		else cout<<"No\n";
    	}
    	return 0;
    }
    

    AC自动机

    class AC{
    	private:
    		struct node{
    			int idx,fail,du,s;
    			int son[27];
    			void init(){
    				memset(son,0,sizeof son);
    				idx=fail=du=s=0;
    			}
    		}s[N];
    	public:
    		int cnt,ans[N],ids;
    		void init(){
    			cnt=ids=0;
    			memset(ans,0,sizeof ans);
    			s[0].init();
    		}
    		void adg(string c,int &id){
    			int u=0;
    			rep(i,1,c.size()){
    				if(s[u].son[c[i-1]-'a']==0){
    					s[u].son[c[i-1]-'a']=++cnt;
    					s[cnt].init();
    				}
    				u=s[u].son[c[i-1]-'a'];
    			}
    			if(s[u].idx==0){
    				s[u].idx=++ids;
    			}
    			id=s[u].idx;
    		}
    		void add(){
    			queue<int> q;
    			rep(i,0,25){
    				if(s[0].son[i]!=0) q.push(s[0].son[i]);
    			}
    			while(q.size()){
    				int u=q.front();
    				q.pop();
    				rep(i,0,25){
    					if(s[u].son[i]!=0){
    						s[s[u].son[i]].fail=s[s[u].fail].son[i];
    						s[s[s[u].fail].son[i]].du++;
    						q.push(s[u].son[i]);
    					}
    					else{
    						s[u].son[i]=s[s[u].fail].son[i];
    					}
    				}
    			}
    		}
    		void tp(){
    			queue<int> q;
    			rep(i,0,cnt){
    				if(s[i].du==0) q.push(i);
    			}
    			while(q.size()){
    				int u=q.front();
    				q.pop();
    				ans[s[u].idx]=s[u].s;
    				int v=s[u].fail;
    				s[v].s+=s[u].s;
    				s[v].du--;
    				if(s[v].du==0){
    					q.push(v);
    				}
    			}
    		}
    		void find(string c){
    			int u=0;
    			rep(i,1,c.size()){
    				u=s[u].son[c[i-1]-'a'];
    				s[u].s++;
    			}
    			tp();
    		}
    };
    

    AC自动机(含匹配程度)

    class AC{
    	private:
    		struct node{
    			int idx,fail,du,s;
    			int son[27];
    			void init(){
    				memset(son,0,sizeof son);
    				idx=fail=du=s=0;
    			}
    		}s[N];
    	public:
    		int cnt,ans[N],v[N],ids;
    		void init(){
    			cnt=ids=0;
    			memset(ans,0,sizeof ans);
    			memset(v,0,sizeof v);
    			s[0].init();
    		}
    		void adg(string c,int &id){
    			int u=0;
    			rep(i,1,c.size()){
    				if(s[u].son[c[i-1]-'A']==0){
    					s[u].son[c[i-1]-'A']=++cnt;
    					s[cnt].init();
    				}
    				u=s[u].son[c[i-1]-'A'];
    			}
    			if(s[u].idx==0){
    				s[u].idx=++ids;
    			}
    			id=s[u].idx;
    		}
    		void add(){
    			queue<int> q;
    			rep(i,0,25){
    				if(s[0].son[i]!=0) q.push(s[0].son[i]);
    			}
    			while(q.size()){
    				int u=q.front();
    				q.pop();
    				rep(i,0,25){
    					if(s[u].son[i]!=0){
    						s[s[u].son[i]].fail=s[s[u].fail].son[i];
    						s[s[s[u].fail].son[i]].du++;
    						q.push(s[u].son[i]);
    					}
    					else{
    						s[u].son[i]=s[s[u].fail].son[i];
    					}
    				}
    			}
    			int u=0;
    			rep(i,1,c[0].size()){
    				u=s[u].son[c[0][i-1]-'A'];
    				for(int j=u;j&&v[j]==0;j=s[j].fail) v[j]=1;
    			}
    		}
    		void tp(){
    			queue<int> q;
    			rep(i,0,cnt){
    				if(s[i].du==0) q.push(i);
    			}
    			while(q.size()){
    				int u=q.front();
    				q.pop();
    				ans[s[u].idx]=s[u].s;
    				int v=s[u].fail;
    				s[v].s+=s[u].s;
    				s[v].du--;
    				if(s[v].du==0){
    					q.push(v);
    				}
    			}
    		}
    		void find(string c){
    			int u=0;
    			rep(i,1,c.size()){
    				u=s[u].son[c[i-1]-'A'];
    				s[u].s++;
    			}
    			tp();
    		}
    		int finds(string c){
    			int u=0,ans=0;
    			rep(i,1,c.size()){
    				u=s[u].son[c[i-1]-'A'];
    				if(v[u]) ans=i;
    			}
    			return ans;
    		}
    };
    
    最小生成树&并查集总集

    最小生成树(prim)

    #include <bits/stdc++.h>
    #define debug(a) cout<<#a<<"="<<a<<"\n";
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    using namespace std;
    const long long N=1007,M=1e6+7;
    struct node{
    	int u,v;
    }b[M];
    int a[N][N],v[N],dp[N][N],f[N],mi[N],n,m,q;
    int main(){
    	cin>>n>>m>>q;
    	rep(i,1,n){
    		rep(j,1,n){
    			if(i!=j) a[i][j]=INT_MAX;
    		}
    	}
    	rep(i,1,m){
    		int u,v,w;
    		cin>>u>>v>>w;
    		a[u][v]=min(a[u][v],w);
    		a[v][u]=a[u][v];
    		b[i].u=u;
    		b[i].v=v;
    	}
    	memset(mi,0x3f3f,sizeof mi);
    	f[1]=1;
    	mi[1]=0;
    	rep(i,1,n){
    		int k=0;
    		rep(j,1,n){
    			if(v[j]==0&&mi[j]<mi[k]){
    				k=j;
    			}
    		}
    		rep(j,1,n){
    			if(v[j]){
    				dp[j][k]=max(dp[j][f[k]],a[f[k]][k]);
    				dp[k][j]=dp[j][k];
    			}
    		}
    		v[k]=1;
    		rep(j,1,n){
    			if(v[j]==0&&a[k][j]<mi[j]){
    				mi[j]=a[k][j];
    				f[j]=k;
    			}
    		}
    	}
    	rep(i,1,q){
    		int x,y,z1,z2;
    		cin>>x>>y;
    		z1=b[x].u;
    		z2=b[x].v;
    		if(dp[z1][z2]>=y) cout<<"Yes\n";
    		else cout<<"No\n";
    	}
    	return 0;
    }
    

    最小生成树(krustal)

    #include <bits/stdc++.h>
    #define debug(a) cout<<#a<<"="<<a<<"\n";
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    using namespace std;
    const long long N=1e6+7;
    struct node{
    	double x,y;
    }d[N];
    struct no{
    	double n;
    	int u,v;
    }c[N];
    double ans=0;
    int a[N],n,m,sum;
    bool cmp(no a,no b){
    	return a.n<b.n;
    }
    int find(int x){
    	if(a[x]!=x) a[x]=find(a[x]);
    	return a[x];
    }
    int main(){
    	while(cin>>n&&n!=0){
    		ans=sum=m=0;
    		rep(i,1,n){
    			cin>>d[i].x>>d[i].y;
    		}
    		rep(i,1,n){
    			rep(j,1,n){
    				if(i!=j){
    					c[++sum]={sqrt(fabs(d[i].x-d[j].x)*fabs(d[i].x-d[j].x)+fabs(d[i].y-d[j].y)*fabs(d[i].y-d[j].y)),i,j};
    				}
    			}
    			a[i]=i;
    		}
    		sort(c+1,c+1+sum,cmp);
    		int i=1;
    		while(m!=n-1){
    			int x=c[i].u,y=c[i].v;
    			int p=find(x),q=find(y);
    			if(p!=q){
    				a[p]=q;
    				m++;
    				ans+=c[i].n;
    			}
    			i++;
    		}
    		printf("%.2lf\n",ans);
    	}
    	return 0;
    }
    

    并查集

    int find(int x){
    	if(a[x]!=x) a[x]=find(a[x]);
    	return a[x];
    }
    
    莫队总集

    莫队

    #include <bits/stdc++.h>
    #define debug(a) cout<<#a<<"="<<a<<"\n";
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    using namespace std;
    const int N=5e4+7,M=2e2+7;
    int n,m,a[N],nn,X[N],b[N],f[N];
    long long s,an[N];
    struct node{
    	int s,l,r;
    };
    node c[N];
    struct ques{
    	int l,r,id;
    };
    ques q[N],qq[N];
    void adg(int &l,int &r,int x,int y,int z){
    	int d=x?l:r;
    	if(x) l+=y;
    	else r+=y;
    	if(z==0){
    		s-=f[a[d]]*f[a[d]];
    		f[a[d]]--;
    		s+=f[a[d]]*f[a[d]];
    	}
    	d+=y;
    	if(z==1){
    		s-=f[a[d]]*f[a[d]];
    		f[a[d]]++;
    		s+=f[a[d]]*f[a[d]];	
    	}
    }
    bool cmp(ques a,ques bb){
    	if(b[a.l]!=b[bb.l]) return b[a.l]<b[bb.l];
    	if(b[a.l]&1) return a.r<bb.r;
    	return a.r>bb.r;
    }
    void md(){
    	int l=q[1].l,r=q[1].r;
    	rep(i,l,r){
    		s-=f[a[i]]*f[a[i]];
    		f[a[i]]++;
    		s+=f[a[i]]*f[a[i]];
    	}
    	an[q[1].id]=s;
    	rep(i,2,m){
    		while(l>q[i].l) adg(l,r,1,-1,1);
    		while(r<q[i].r) adg(l,r,0,1,1);
    		while(l<q[i].l) adg(l,r,1,1,0);
    		while(r>q[i].r) adg(l,r,0,-1,0);
    		an[q[i].id]=s;
    	}
    }
    int main(){
    	cin>>n>>m;
    	int t=sqrt(n);
    	rep(i,1,n){
    		cin>>a[i];
    		b[i]=(i-1)/t+1;
    		if(c[b[i]].l==0) c[b[i]].l=i;
    		c[b[i]].r=i;
    		X[i]=a[i];
    	}
    	sort(X+1,X+1+n);
    	nn=unique(X+1,X+1+n)-X-1;
    	rep(i,1,n){
    		a[i]=lower_bound(X+1,X+1+nn,a[i])-X;
    	}
    	rep(i,1,m){
    		cin>>q[i].l>>q[i].r;
    		q[i].id=i;
    		qq[i]=q[i];
    	}
    	sort(q+1,q+1+m,cmp);
    	md();
    	rep(i,1,m){
    		long long l=qq[i].l,r=qq[i].r;
    		if(an[i]==(r-l+1)) cout<<"0/1\n";
    		else{
    			long long x=an[i]-(r-l+1),y=(r-l+1)*(r-l);
    			int g=__gcd(x,y);
    			x/=g;
    			y/=g;
    			cout<<x<<"/"<<y<<"\n";
    		}
    	}
    	return 0;
    }
    

    回滚莫队(只加不减)

    #include <bits/stdc++.h>
    #define debug(a) cout<<#a<<"="<<a<<"\n";
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    using namespace std;
    const int N=2e5+7,M=2e2+7;
    int n,m,a[N],nn,b[N],f[N],f2[N];
    long long X[N];
    long long s,an[N];
    struct node{
    	int s,l,r;
    };
    node c[N];
    struct ques{
    	int l,r,id;
    };
    ques q[N];
    void adg(int &l,int &r,int x,int y,int z){
    	int d=x?l:r;
    	if(x) l+=y;
    	else r+=y;
    	if(z==0){
    		f[a[d]]--;
    	}
    	d+=y;
    	if(z==1){
    		f[a[d]]++;
    		s=max(s,f[a[d]]*X[a[d]]);
    	}
    }
    bool cmp(ques a,ques bb){
    	if(b[a.l]!=b[bb.l]) return b[a.l]<b[bb.l];
    	return a.r<bb.r;
    }
    void md(){
    	int l=1,r=0;
    	rep(i,1,m){
    		if(b[q[i].l]!=b[q[i-1].l]){
    			rep(j,l,r){
    				f[a[j]]=0;
    			}
    			l=c[b[q[i].l]].r+1;
    			r=c[b[q[i].l]].r;
    			s=0;
    		}
    		if(b[q[i].l]==b[q[i].r]){
    			long long ss=0;
    			rep(j,q[i].l,q[i].r){
    				f2[a[j]]++;
    				ss=max(ss,f2[a[j]]*X[a[j]]);
    			}
    			rep(j,q[i].l,q[i].r){
    				f2[a[j]]--;
    			}
    			an[q[i].id]=ss;
    			continue;
    		}
    		while(r<q[i].r) adg(l,r,0,1,1);
    		long long la=s;
    		while(l>q[i].l) adg(l,r,1,-1,1);
    		while(l<c[b[q[i].l]].r+1) adg(l,r,1,1,0);
    		an[q[i].id]=s;
    		s=la;
    	}
    }
    int main(){
    	cin>>n>>m;
    	int t=sqrt(n);
    	rep(i,1,n){
    		cin>>a[i];
    		b[i]=(i-1)/t+1;
    		if(c[b[i]].l==0) c[b[i]].l=i;
    		c[b[i]].r=i;
    		X[++nn]=a[i];
    	}
    	sort(X+1,X+1+nn);
    	nn=unique(X+1,X+1+nn)-X-1;
    	rep(i,1,n){
    		a[i]=lower_bound(X+1,X+1+nn,a[i])-X;
    	}
    	rep(i,1,m){
    		cin>>q[i].l>>q[i].r;
    		q[i].id=i;
    	}
    	sort(q+1,q+1+m,cmp);
    	md();
    	rep(i,1,m){
    		cout<<an[i]<<"\n";
    	}
    	return 0;
    }
    
    网络流总集
    上下界网络流

    无源汇上下界可行流

    #include <bits/stdc++.h>
    #define debug(a) cout<<#a<<"="<<a<<"\n";
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    using namespace std;
    const long long N=2e3+7,M=3e5+7;
    long long n,m,d[N],d2[N],S,T,t=1,t2,p[M],now[N],son[M],val[M],noww[N],nowww[N],h[N],ans;
    struct node{
    	long long u,v,w1,w2;
    };
    node a[M];
    void put(int a,int b,long long c){
    	p[++t]=now[a];
    	now[a]=t;
    	son[t]=b;
    	val[t]=c;
    }
    bool bfs(){
    	rep(i,1,n+2){
    		noww[i]=now[i];
    		h[i]=0;
    	}
    	h[S]=1;
    	queue<int> q;
    	q.push(S);
    	while(q.size()){
    		int u=q.front();
    		q.pop();
    		for(int i=noww[u];i;i=p[i]){
    			int y=son[i];
    			if(val[i]&&h[y]==0){
    				h[y]=h[u]+1;
    				q.push(y);
    				if(y==T) return 1;
    			}
    		}
    	}
    	return 0;
    }
    long long dfs(int x,long long s){
    	if(x==T) return s;
    	long long sum=0;
    	for(long long &i=noww[x];i;i=p[i]){
    		int y=son[i];
    		if(val[i]&&h[y]==h[x]+1){
    			long long ss=dfs(y,min(s,val[i]));
    			val[i]-=ss;
    			val[i^1]+=ss;
    			s-=ss;
    			sum+=ss;
    			if(s==0) break;
    		}
    	}
    	if(sum==0) h[x]=0;
    	return sum;
    }
    void dinic(){
    	while(bfs()){
    		ans+=dfs(S,1e18);
    	}
    }
    int main(){
    	cin>>n>>m;
    	S=n+1,T=n+2;
    	long long ss=0,sss=0,sss2=0;
    	rep(i,1,m){
    		long long u,v,w1,w2,w;
    		cin>>u>>v>>w1>>w2;
    		a[i]={u,v,w1,w2};
    		w=w2-w1;
    		ss+=w1;
    		put(u,v,w);
    		put(v,u,0);
    		d2[u]+=w1;
    		d[v]+=w1;
    	}
    	t2=t;
    	rep(i,1,n){
    		nowww[i]=now[i];
    	}
    	rep(i,1,n){
    		if(d[i]>d2[i]){
    			sss+=d[i]-d2[i];
    			put(S,i,d[i]-d2[i]);
    			put(i,S,0);
    		}
    		else if(d[i]<d2[i]){
    			sss2+=d2[i]-d[i];
    			put(i,T,d2[i]-d[i]);
    			put(T,i,0);
    		}
    	}
    	if(sss!=sss2){
    		cout<<"NO\n";
    		return 0;
    	}
    	dinic();
    	if(ans==sss){
    		cout<<"YES\n";
    		rep(i,1,m){
    			cout<<a[i].w1+val[i*2+1]<<"\n";
    		}
    	}
    	else cout<<"NO\n";
    	return 0;
    }
    

    有源汇上下界最大流

    #include <bits/stdc++.h>
    #define debug(a) cout<<#a<<"="<<a<<"\n";
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    using namespace std;
    const long long N=2e3+7,M=3e5+7;
    long long n,m,S2,T2,d[N],d2[N],S,T,t=1,t2,p[M],now[N],son[M],val[M],noww[N],nowww[N],h[N],ans;
    struct node{
    	long long u,v,w1,w2;
    };
    node a[M];
    void put(int a,int b,long long c){
    	p[++t]=now[a];
    	now[a]=t;
    	son[t]=b;
    	val[t]=c;
    }
    bool bfs(){
    	rep(i,1,n+2){
    		noww[i]=now[i];
    		h[i]=0;
    	}
    	h[S]=1;
    	queue<int> q;
    	q.push(S);
    	while(q.size()){
    		int u=q.front();
    		q.pop();
    		for(int i=noww[u];i;i=p[i]){
    			int y=son[i];
    			if(val[i]&&h[y]==0){
    				h[y]=h[u]+1;
    				q.push(y);
    				if(y==T) return 1;
    			}
    		}
    	}
    	return 0;
    }
    long long dfs(int x,long long s){
    	if(x==T) return s;
    	long long sum=0;
    	for(long long &i=noww[x];i;i=p[i]){
    		int y=son[i];
    		if(val[i]&&h[y]==h[x]+1){
    			long long ss=dfs(y,min(s,val[i]));
    			val[i]-=ss;
    			val[i^1]+=ss;
    			s-=ss;
    			sum+=ss;
    			if(s==0) break;
    		}
    	}
    	if(sum==0) h[x]=0;
    	return sum;
    }
    void dinic(){
    	while(bfs()){
    		ans+=dfs(S,1e18);
    	}
    }
    int main(){
    	cin>>n>>m>>S2>>T2;
    	S=n+1,T=n+2;
    	long long ss=0,sss=0,sss2=0;
    	rep(i,1,m){
    		long long u,v,w1,w2,w;
    		cin>>u>>v>>w1>>w2;
    		a[i]={u,v,w1,w2};
    		w=w2-w1;
    		ss+=w1;
    		put(u,v,w);
    		put(v,u,0);
    		d2[u]+=w1;
    		d[v]+=w1;
    	}
    	t2=t;
    	rep(i,1,n+2){
    		nowww[i]=now[i];
    	}
    	put(T2,S2,1e18);
    	put(S2,T2,0);
    	rep(i,1,n){
    		if(d[i]>d2[i]){
    			sss+=d[i]-d2[i];
    			put(S,i,d[i]-d2[i]);
    			put(i,S,0);
    		}
    		else if(d[i]<d2[i]){
    			sss2+=d2[i]-d[i];
    			put(i,T,d2[i]-d[i]);
    			put(T,i,0);
    		}
    	}
    	if(sss!=sss2){
    		cout<<"please go home to sleep\n";
    		return 0;
    	}
    	dinic();
    	if(ans!=sss){
    		cout<<"please go home to sleep\n";
    		return 0;
    	}
    	ans=val[t2+2];
    	t=t2;
    	rep(i,1,n+2){
    		now[i]=nowww[i];
    	}
    	S=S2,T=T2;
    	dinic();
    	cout<<ans;
    	return 0;
    }
    

    有源汇上下界最小流

    #include <bits/stdc++.h>
    #define debug(a) cout<<#a<<"="<<a<<"\n";
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    using namespace std;
    const long long N=5e5+7,M=5e5+7;
    long long n,m,S2,T2,d[N],d2[N],S,T,t=1,t2,p[M],now[N],son[M],val[M],noww[N],nowww[N],h[N],ans;
    struct node{
    	long long u,v,w1,w2;
    };
    node a[M];
    void put(int a,int b,long long c){
    	p[++t]=now[a];
    	now[a]=t;
    	son[t]=b;
    	val[t]=c;
    }
    bool bfs(){
    	rep(i,1,n+2){
    		noww[i]=now[i];
    		h[i]=0;
    	}
    	h[S]=1;
    	queue<int> q;
    	q.push(S);
    	while(q.size()){
    		int u=q.front();
    		q.pop();
    		for(int i=noww[u];i;i=p[i]){
    			int y=son[i];
    			if(val[i]&&h[y]==0){
    				h[y]=h[u]+1;
    				q.push(y);
    				if(y==T) return 1;
    			}
    		}
    	}
    	return 0;
    }
    long long dfs(int x,long long s){
    	if(x==T) return s;
    	long long sum=0;
    	for(long long &i=noww[x];i;i=p[i]){
    		int y=son[i];
    		if(val[i]&&h[y]==h[x]+1){
    			long long ss=dfs(y,min(s,val[i]));
    			val[i]-=ss;
    			val[i^1]+=ss;
    			s-=ss;
    			sum+=ss;
    			if(s==0) break;
    		}
    	}
    	if(sum==0) h[x]=0;
    	return sum;
    }
    void dinic(){
    	while(bfs()){
    		ans+=dfs(S,1e18);
    	}
    }
    int main(){
    	cin>>n>>m>>S2>>T2;
    	S=n+1,T=n+2;
    	long long sss=0,sss2=0;
    	rep(i,1,m){
    		long long u,v,w1,w2,w;
    		cin>>u>>v>>w1>>w2;
    		a[i]={u,v,w1,w2};
    		w=w2-w1;
    		put(u,v,w);
    		put(v,u,0);
    		d2[u]+=w1;
    		d[v]+=w1;
    	}
    	t2=t;
    	rep(i,1,n+2){
    		nowww[i]=now[i];
    	}
    	put(T2,S2,1e18);
    	put(S2,T2,0);
    	rep(i,1,n){
    		if(d[i]>d2[i]){
    			sss+=d[i]-d2[i];
    			put(S,i,d[i]-d2[i]);
    			put(i,S,0);
    		}
    		else if(d[i]<d2[i]){
    			sss2+=d2[i]-d[i];
    			put(i,T,d2[i]-d[i]);
    			put(T,i,0);
    		}
    	}
    	if(sss!=sss2){
    		cout<<"please go home to sleep\n";
    		return 0;
    	}
    	dinic();
    	if(ans!=sss){
    		cout<<"please go home to sleep\n";
    		return 0;
    	}
    	long long ss=val[t2+2];
    	t=t2;
    	rep(i,1,n+2){
    		now[i]=nowww[i];
    	}
    	S=T2,T=S2;
    	ans=0;
    	dinic();
    	cout<<ss-ans;
    	return 0;
    }
    

    有源汇上下界费用可行流

    #include <bits/stdc++.h>
    #define debug(a) cout<<#a<<"="<<a<<"\n";
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    using namespace std;
    const long long N=2e3+7,M=3e5+7,INF=1e18;
    long long n,m,b[N],S2,T2,d[N],d2[N],S,T,t=1,vis[N],p[M],now[N],son[M],val[M],coss[M],noww[N],h[N],ans,ans2;
    struct node{
    	long long u,v,w1,w2,c;
    };
    node a[M];
    void put(int a,int b,long long c,long long d){
    	p[++t]=now[a];
    	now[a]=t;
    	son[t]=b;
    	val[t]=c;
    	coss[t]=d;
    }
    bool bfs(){
    	rep(i,1,n+3){
    		noww[i]=now[i];
    		vis[i]=0;
    		h[i]=1e18;
    	}
    	h[S]=0;
    	queue<int> q;
    	q.push(S);
    	bool flag=0;
    	while(q.size()){
    		int u=q.front();
    		q.pop();
    		vis[u]=0;
    		if(u==T) flag=1;
    		for(int i=noww[u];i;i=p[i]){
    			int y=son[i];
    			if(val[i]&&h[y]>h[u]+coss[i]){
    				h[y]=h[u]+coss[i];
    				if(vis[y]==0){
    					q.push(y);
    					vis[y]=1;
    				}
    			}
    		}
    	}
    	return flag;
    }
    long long dfs(int x,long long s,long long &sss){
    	if(x==T) return s;
    	vis[x]=1;
    	long long sum=0;
    	for(long long &i=noww[x];i;i=p[i]){
    		int y=son[i];
    		if(vis[y]==0&&val[i]&&h[y]==h[x]+coss[i]){
    			long long ss=dfs(y,min(s,val[i]),sss);
    			val[i]-=ss;
    			val[i^1]+=ss;
    			s-=ss;
    			sum+=ss;
    			sss+=coss[i]*ss;
    			if(s==0) break;
    		}
    	}
    	if(sum==0) h[x]=0;
    	vis[x]=0;
    	return sum;
    }
    void dinic(){
    	while(bfs()){
    		ans+=dfs(S,1e18,ans2);
    	}
    }
    int main(){
    	cin>>n;
    	S2=1,T2=n+1;
    	S=n+2,T=n+3;
    	long long ss=0,sss=0,sss2=0;
    	rep(i,1,n){
    		cin>>b[i];
    		rep(j,1,b[i]){
    			long long y,z;
    			cin>>y>>z;
    			a[++ss]={i,y,1,INF,z};
    		}
    		a[++ss]={i,T2,0,INF,0};
    	}
    	rep(i,1,ss){
    		long long u=a[i].u,v=a[i].v,w1=a[i].w1,w2=a[i].w2,c=a[i].c,w;
    		w=w2-w1;
    		put(u,v,w,c);
    		put(v,u,0,-c);
    		ans2+=c*w1;
    		d2[u]+=w1;
    		d[v]+=w1;
    	}
    	put(T2,S2,1e18,0);
    	put(S2,T2,0,0);
    	rep(i,1,n+1){
    		if(d[i]>d2[i]){
    			sss+=d[i]-d2[i];
    			put(S,i,d[i]-d2[i],0);
    			put(i,S,0,0);
    		}
    		else if(d[i]<d2[i]){
    			sss2+=d2[i]-d[i];
    			put(i,T,d2[i]-d[i],0);
    			put(T,i,0,0);
    		}
    	}
    	dinic();
    	cout<<ans2<<"\n";
    	return 0;
    }
    

    最大流(dinic)

    #include <bits/stdc++.h>
    #define debug(a) cout<<#a<<"="<<a<<"\n";
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    using namespace std;
    const long long N=2e3+7,M=2e4+7;
    long long n,m,S,T,t=1,p[M],now[M],son[M],val[N],noww[M],h[N],ans;
    void put(int a,int b,long long c){
    	p[++t]=now[a];
    	now[a]=t;
    	son[t]=b;
    	val[t]=c;
    }
    bool bfs(){
    	rep(i,1,n){
    		noww[i]=now[i];
    		h[i]=0;
    	}
    	h[S]=1;
    	queue<int> q;
    	q.push(S);
    	while(q.size()){
    		int u=q.front();
    		q.pop();
    		for(int i=noww[u];i;i=p[i]){
    			int y=son[i];
    			if(val[i]&&h[y]==0){
    				h[y]=h[u]+1;
    				q.push(y);
    				if(y==T) return 1;
    			}
    		}
    	}
    	return 0;
    }
    long long dfs(int x,long long s){
    	if(x==T) return s;
    	long long sum=0;
    	for(long long &i=noww[x];i;i=p[i]){
    		int y=son[i];
    		if(val[i]&&h[y]==h[x]+1){
    			long long ss=dfs(y,min(s,val[i]));
    			val[i]-=ss;
    			val[i^1]+=ss;
    			s-=ss;
    			sum+=ss;
    			if(s==0) break;
    		}
    	}
    	if(sum==0) h[x]=0;
    	return sum;
    }
    void dinic(){
    	while(bfs()){
    		ans+=dfs(S,1e18);
    	}
    }
    int main(){
    	cin>>m>>n;
    	S=1,T=n;
    	rep(i,1,m){
    		long long u,v,w;
    		cin>>u>>v>>w;
    		put(u,v,w);
    		put(v,u,0);
    	}
    	dinic();
    	cout<<ans<<"\n";
    	return 0;
    }
    

    费用流(最小费用最大流)

    #include <bits/stdc++.h>
    #define debug(a) cout<<#a<<"="<<a<<"\n";
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    using namespace std;
    const long long N=5e3+7,M=1e5+7;
    long long n,m,d,S,T,t=1,p[M],now[N],son[M],val[M],coss[M],noww[N],h[N],vis[N],ans,ans2;
    void put(int a,int b,long long c,long long d){
    	p[++t]=now[a];
    	now[a]=t;
    	son[t]=b;
    	val[t]=c;
    	coss[t]=d;
    }
    bool bfs(){
    	rep(i,1,n){
    		noww[i]=now[i];
    		vis[i]=0;
    		h[i]=1e18;
    	}
    	h[S]=0;
    	queue<int> q;
    	q.push(S);
    	bool flag=0;
    	while(q.size()){
    		int u=q.front();
    		q.pop();
    		vis[u]=0;
    		if(u==T) flag=1;
    		for(int i=noww[u];i;i=p[i]){
    			int y=son[i];
    			if(val[i]&&h[y]>h[u]+coss[i]){
    				h[y]=h[u]+coss[i];
    				if(vis[y]==0){
    					q.push(y);
    					vis[y]=1;
    				}
    			}
    		}
    	}
    	return flag;
    }
    long long dfs(int x,long long s,long long &sss){
    	if(x==T) return s;
    	vis[x]=1;
    	long long sum=0;
    	for(long long &i=noww[x];i;i=p[i]){
    		int y=son[i];
    		if(vis[y]==0&&val[i]&&h[y]==h[x]+coss[i]){
    			long long ss=dfs(y,min(s,val[i]),sss);
    			val[i]-=ss;
    			val[i^1]+=ss;
    			s-=ss;
    			sum+=ss;
    			sss+=coss[i]*ss;
    			if(s==0) break;
    		}
    	}
    	if(sum==0) h[x]=0;
    	vis[x]=0;
    	return sum;
    }
    void dinic(){
    	while(bfs()){
    		ans+=dfs(S,1e18,ans2);
    	}
    }
    int main(){
    	cin>>n>>m>>S>>T;
    	rep(i,1,m){
    		long long u,v,w,cw;
    		cin>>u>>v>>w>>cw;
    		put(u,v,w,cw);
    		put(v,u,0,-cw);
    	}
    	dinic();
    	cout<<ans<<" "<<ans2<<"\n";
    	return 0;
    }
    
    数学常用&&高精度总集
    高精度总集

    高乘低

      void mul(long long *a,int b){
    	long long s=0;
    	rep(i,1,a[0]){
    		a[i]=a[i]*b+s;
    		s=a[i]/B;
    		a[i]%=B;
    	}
    	while(s) a[++a[0]]=s,s/=B;
    }
    

    高除低

    void div(long long *a,int b){
    	long long s=0;
    	for(int i=a[0];i>=1;i--){
    		long long aa=a[i];
    		a[i]=(s+a[i])/b;
    		s=(s+aa)%b*B;
    	}
    	while(a[0]!=1&&a[a[0]]==0) a[0]--;
    }
    

    高减高

    void sub(long long *a,long long *b){
    	long long s=0;
    	rep(i,1,a[0]){
    		a[i]-=s;
    		if(a[i]<b[i]){
    			s=1;
    			a[i]+=B;
    		}
    		else{
    			s=0;
    		}
    		a[i]-=b[i];
    	}
    	while(a[0]!=1&&a[a[0]]==0) a[0]--;
    }
    

    高加高

    void add(long long *a,long long *b){
    	long long s=0;
    	rep(i,1,max(a[0],b[0])){
    		a[i]=a[i]+b[i]+s;
    		s=a[i]/B;
    		a[i]%=B;
    	}
    	while(s) a[++a[0]]=s,s/=B;
    }
    

    判断素数

    bool sushu(long long x){
    	if(x<=1) return 0;
    	long long t=sqrt(x);
    	rep(i,2,t){
    		if(x%i==0){
    			return 0;
    		}
    	}
    	return 1;
    }
    

    快速幂

    long long qupow(long long a,long long b,long long p){
    	long long s=1;
    	a%=p;
    	while(b){
    		if(b%2==1) s=(a*s)%p;
    		a*=a;
    		b>>=1;
    		a%=p;
    	}
    	return s;
    }
    

    欧拉筛

    void ola(int nn){
    	rep(i,2,nn){
    		if(v[i]==0) ans[++s]=i;
    		for(int j=1;j<=s&&ans[j]*i<=nn;++j){
    			v[ans[j]*i]=1;
    			if(i%ans[j]==0) break;
    		}
    	}
    }
    

    欧拉扩展

    long long bds(long long a,long long b,long long c,long long &xx,long long &yy){
    	if(b==0){
    		xx=c/a;
    		yy=0;
    		return a;
    	}
    	long long nx,ny;
    	long long f=bds(b,a%b,c,nx,ny);
    	xx=ny;
    	yy=nx-a/b*ny;
    	return f;
    }
    void mod_t(long long a,long long b,long long n){
    	long long d,x,y;
    	d=bds(a,n,b,x,y);
    	if(b%d){
    		cout<<-1;
    		return;
    	}
    	long long t=n/d;
    	if(t<0) t=-t;
    	x=(x%t+t)%t;
    	cout<<x;
    	// rep(i,1,d){
    	// 	cout<<x+(i-1)*b/d<<"\n";
    	// }
    }
    

    扩展BSGS魔法对数(第一类高次同余方程)

    long long exBSGS(long long a,long long b,long long n){
    	a%=n;
    	b%=n;
    	if(b==1||n==1) return 0;
    	if(a==b) return 1;
    	map<int,pair<long long,long long> > q;
    	long long f=n,nn=n;
    	rep(i,1,s){
    		if(nn%ans[i]==0){
    			f=f/ans[i]*(ans[i]-1);
    			while(nn%ans[i]==0) nn/=ans[i];
    		}
    	}
    	if(nn!=1){
    		f=f/nn*(nn-1);
    	}
    	long long t=sqrt(2*f),anss=-1;
    	if(t*t!=2*f) t++;
    	rep(i,0,t){
    		if(qupow(a,i,n)==b) return i;
    	}
    	if(b==0){
    		return -1;
    	}
    	rep(i,1,t){
    		long long pp=qupow(a,t*i,n);
    		if(q.count(pp)==0) q[pp].first=t*i;
    		else if(q[pp].second==0) q[pp].second=t*i;
    	}
    	rep(i,0,t){
    		long long pp=b*qupow(a,i,n)%n;
    		if(q.count(pp)){
    			if(q[pp].first&&qupow(a,q[pp].first-i,n)%n==b){
    				if(anss==-1) anss=q[pp].first-i;
    				else anss=min(anss,q[pp].first-i);
    			}
    			if(q[pp].second!=0&&qupow(a,q[pp].second-i,n)%n==b){
    				if(anss==-1) anss=q[pp].second-i;
    				else anss=min(anss,q[pp].second-i);
    			}
    		}
    	}
    	return anss;
    }
    

    原根

    long long Oroot(long long n){
    	s=0;
    	long long tt=sqrt(n-1),nn=n-1;
    	rep(i,2,tt){
    		if(nn%i==0){
    			ans[++s]=i;
    			while(nn%i==0) nn/=i;
    		}
    	}
    	if(nn!=1){
    		ans[++s]=nn;
    	}
    	rep(a,1,n){
    		bool flag=1;
    		rep(j,1,s){
    			if(qupow(a,(n-1)/ans[j],n)==1){
    				flag=0;
    				break;
    			}
    		}
    		if(flag) return a;
    	}
    	return -1;
    }
    

    魔法开根(第二类高次同余方程)

    long long mod_sq(long long k,long long b,long long n){
      if(b==0) return 0;
    	long long O=Oroot(n);
    	long long m=exBSGS(O,b,n);
    	long long y=mod_t(k,m,n-1);
    	if(y==-1){
    		return -1;
    	}
    	return qupow(O,y,n);
    }
    

    矩阵运算

    struct mat{
    	vector<vector<long long> > s;
    	long long n,m;
    	mat(long long x,long long y){
    		n=x;
    		m=y;
    		s.resize(n+1);
    		fill(s.begin(),s.end(),vector<long long>(m+1,0) );
    	}
    	friend mat operator+(const mat &a,const mat &b){
    		mat sss={a.n,a.m};
    		rep(i,0,a.n){
    			rep(j,0,a.m){
    				sss.s[i][j]=(a.s[i][j]+b.s[i][j])%M;
    			}
    		}
    		return sss;
    	}
    	friend mat operator-(const mat &a,const mat &b){
    		mat sss={a.n,a.m};
    		rep(i,0,a.n){
    			rep(j,0,a.m){
    				sss.s[i][j]=(a.s[i][j]-b.s[i][j]+M)%M;
    			}
    		}
    		return sss;
    	}
    	friend mat operator*(const mat &a,const mat &b){
    		mat sss={a.n,b.m};
    		rep(i,0,a.n){
    			rep(j,0,a.m){
    				rep(k,0,b.m){
    					sss.s[i][k]=(sss.s[i][k]+a.s[i][j]*b.s[j][k]%M)%M;
    				}
    			}
    		}
    		return sss;
    	}
    	friend mat operator^(const mat &a,const long long &b){
    		mat sss={a.n,a.m},aa=a;
    		rep(i,0,a.n) sss.s[i][i]=1;
    		long long bb=b;
    		while(bb){
    			if(bb%2==1) sss=(sss*aa);
    			aa=aa*aa;
    			bb>>=1;
    		}
    		return sss;
    	}
    };
    

    高斯消元

    bool eli(vector<vector<double> > &a,int n){
    	bool f=1;
    	int iii=1;
    	rep(i,1,n){
    		int id=iii;
    		rep(j,iii+1,n){
    			if(fabs(a[id][i])<fabs(a[j][i])){
    				id=j;
    			}
    		}
    		if(fabs(a[id][i])<M){
    			f=0;
    			continue;
    		}
    		if(id!=iii) swap(a[id],a[iii]);
    		double s=a[iii][i];
    		rep(j,1,n){
    			if(j==iii) continue;
    			s=a[j][i]/a[iii][i];
    			rep(k,i,n+1){
    				a[j][k]-=a[iii][k]*s;
    			}
    		}
    		iii++;
    	}
    	return f;
    }
    

    高斯消元(异或)

    bool eli(vector<vector<int> > &a,int n){
    	bool f=1;
    	int iii=1;
    	rep(i,1,n){
    		int id=iii;
    		rep(j,iii+1,n){
    			if(abs(a[j][i])==1){
    				id=j;
    			}
    		}
    		if(abs(a[id][i])==0){
    			continue;
    		}
    		if(id!=iii) swap(a[id],a[iii]);
    		rep(j,1,n){
    			if(j==iii) continue;
    			if(a[j][i]==0) continue;
    			rep(k,i,n+1){
    				a[j][k]^=a[iii][k];
    			}
    		}
    		iii++;
    	}
    	rep(i,1,n){
    		bool ff=1;
    		rep(j,1,n){
    			if(a[i][j]){
    				ff=0;
    				break;
    			}
    		}
    		if(ff&&a[i][n+1]){
    			f=0;
    			break;
    		}
    	}
    	iii--;
    	ans=qupow(2,n-iii,M);
    	return f;
    }
    
    其他

    链式前向星

    void put(int a,int b){
    	p[++t]=now[a];
    	now[a]=t;
    	son[t]=b;
    }
    

    拓扑排序

    void tp(){
    	long long ans=0,s=0;
    	queue<int> q;
    	rep(i,1,n){
    		if(t[i]==0){
    			d[i]=100;
    			q.push(i);
    			s++;
    		}
    	}
    	while(!q.empty()){
    		int x=q.front();
    		q.pop();
    		for(int i=0;i<g[x].size();++i){
    			int j=g[x][i];
    			if(t[j]){
    				t[j]--;
    				d[j]=max(d[j],d[x]+1);
    				if(t[j]==0){
    					q.push(j);
    					s++;
    				}
    			}
    		}
    	}
    	if(s!=n){
    		cout<<"Poor Xed";
    	}
    	else{
    		rep(i,1,n){
    			ans+=d[i];
    		}
    		cout<<ans;
    	}
    }
    

    树状数组

    class fenwicktree{
    	private:
    		vector<long long> c;
    		long long n;
    		int lowbit(int x){
    			return (x&-x);
    		}
    	public:
    		fenwicktree(int x){
    			n=x;
    			c.resize(n+1);
    			fill(c.begin(),c.end(),0);
    		}
    		void put(long long x,long long num){
    			while(x<=n){
    				c[x]+=num;
    				x+=lowbit(x);
    			}
    		}
    		long long sum(long long x){
    			long long ans=0;
    			while(x){
    				ans+=c[x];
    				x-=lowbit(x);
    			}
    			return ans;
    		}
    };
    

    二分图判断(dfs染色)

    bool coldfs(int x,int col){
    	color[x]=col;
    	for(int i=0;i<g[x].size();i++){
    		int j=g[x][i];
    		if(color[j]==col) return 0;
    		if(color[j]==0){
    			if(coldfs(j,col%2+1)==0) return 0;
    		}
    	}
    	return 1;
    }
    

    lca

    int lca(int x,int y){
    	if(h[x]<h[y]){
    		swap(x,y);
    	}
    	for(int i=19;i>=0;i--){
    		if(h[f[x][i]]>=h[y]){
    			x=f[x][i];
    		}
    	}
    	if(x==y) return x;
    	for(int i=19;i>=0;i--){
    		if(f[x][i]!=f[y][i]){
    			x=f[x][i];
    			y=f[y][i];
    		}
    	}
    	return f[x][0];
    }
    

    kmp

    int n,m,nx[N],s[N];
    char a[N],b[N];
    void nxt(){
    	nx[1]=0;
    	int j=0;
    	rep(i,2,m){
    		while(j&&b[j+1]!=b[i]) j=nx[j];
    		if(b[j+1]==b[i]) j++;
    		nx[i]=j;
    	}
    }
    void kmp(){
    	nxt();
    	int j=0;
    	rep(i,1,n){
    		while(j&&b[j+1]!=a[i]) j=nx[j];
    		if(b[j+1]==a[i]) j++;
    		s[i]=j;
    	}
    }
    

    扩展kmp(z函数)

    int n,m,p[N],s[N],ans;
    char a[N],b[N];
    void nxt(){
    	int mid=0,r=0;
    	p[1]=m;
    	rep(i,2,m){
    		if(i>r) p[i]=0;
    		else p[i]=min(r-i+1,p[i-mid+1]);
    		while(i+p[i]<=m&&b[i+p[i]]==b[p[i]+1]) p[i]++;
    		if(i+p[i]-1>r){
    			r=i+p[i]-1;
    			mid=i;
    		}
    	}
    }
    void kkp(){
    	nxt();
    	int mid=0,r=0;
    	rep(i,1,n){
    		if(i>r) s[i]=0;
    		else s[i]=min(r-i+1,p[i-mid+1]);
    		while(i+s[i]<=n&&a[i+s[i]]==b[s[i]+1]) s[i]++;
    		if(i+s[i]-1>r){
    			r=i+s[i]-1;
    			mid=i;
    		}
    	}
    }
    

    分块

    #include <bits/stdc++.h>
    #define debug(a) cout<<#a<<"="<<a<<"\n";
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    using namespace std;
    const long long N=1e6+7;
    long long n,m,a[N],b[N],ans;
    struct node{
    	long long s,l,r;
    };
    node c[N];
    int main(){
    	cin>>n;
    	int t=sqrt(n);
    	rep(i,1,n){
    		cin>>a[i];
    		b[i]=(i-1)/t+1;
    		c[b[i]].s=0;
    		if(c[b[i]].l==0) c[b[i]].l=i;
    		c[b[i]].r=i;
    	}
    	rep(i,1,n){
    		long long id,u,v,x;
    		cin>>id>>u>>v>>x;
    		if(id==0){
    			rep(j,1,b[n]){
    				if(c[j].l>=u&&c[j].r<=v){
    					c[j].s+=x;
    				}
    				else if(c[j].l<u&&c[j].r>v){
    					rep(k,u,v){
    						a[k]+=x;
    					}
    					break;
    				}
    				else if(c[j].l<u&&c[j].r>=u){
    					rep(k,u,c[j].r){
    						a[k]+=x;
    					}
    				}
    				else if(c[j].l<=v&&c[j].r>v){
    					rep(k,c[j].l,v){
    						a[k]+=x;
    					}
    				}
    			}
    		}
    		else{
    			cout<<a[v]+c[b[v]].s<<"\n";
    		}
    	}
    	return 0;
    }
    

    线性基

    class linear_basis{
    	private:
    		bool flag;
    		long long n;
    		vector<long long> bas;
    	public:
    		linear_basis(long long siz){
    			flag=0;
    			n=siz;
    			bas.resize(siz+1);
    			fill(bas.begin(),bas.end(),0);
    		}
    		void adg1(long long x){
    			for(int i=n;i>=0;i--){
    				if(x&(1ll<<i)){
    					if(bas[i]==0){
    						bas[i]=x;
    						return;
    					}
    					else x^=bas[i];
    				}
    			}
    			flag=1;
    		}
    		bool check(long long x){
    			for(int i=n;i>=0;i--){
    				if(x&(1ll<<i)){
    					if(bas[i]==0){
    						return 0;
    					}
    					else x^=bas[i];
    				}
    			}
    			return 1;
    		}
    		long long Max(){
    			long long ans=0;
    			for(int i=n;i>=0;i--){
    				ans=max(ans,ans^bas[i]);
    			}
    			return ans;
    		}
    		long long Min(){
    			if(flag) return 0;
    			rep(i,0,n){
    				if(bas[i]!=0) return bas[i];
    			}
    		}
    		long long finds(long long x){
    			if(flag){
    				if(x==1) return 0;
    				x--;
    			}
    			vector<long long> ans;
    			rep(i,0,n){
    				for(long j=i-1;j>=0;j--){
    					if(bas[i]&(1ll<<j)) bas[i]^=bas[j];
    				}
    				if(bas[i]) ans.push_back(bas[i]);
    			}
    			if(x>=(1ll<<(ans.size()))) return -1;
    			long long s=0;
    			for(int i=0;i<ans.size();i++){
    				if(x&(1ll<<i)) s^=ans[i];
    			}
    			return s;
    		}
    		friend linear_basis operator+(const linear_basis &a,const linear_basis &b){
    			linear_basis s=a;
    			rep(i,0,b.n){
    				if(b.bas[i]){
    					s.adg1(b.bas[i]);
    				}
    			}
    			return s;
    		}
    };
    
    ————————————————————分割线————————————————————
    对拍

    对拍(duipai)

    #include<bits/stdc++.h>
    #define debug(a) cout<<#a<<"="<<a<<"\n";
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    using namespace std;
    int main()
    {
    	while(1){
    		system("data.exe");
    		system("baoli.exe");
    		system("std.exe");
    		if(system("fc std.txt baoli.txt")) break;
    	}
    	return 0;
    }
    

    数据(data)

    #include <bits/stdc++.h>
    #define debug(a) cout<<#a<<"="<<a<<"\n";
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    using namespace std;
    long long Random(long long mod)
    {
    	long long ans=2147483647;
    	ans=ans*rand()%mod+1;
    	return ans;
    }
    int main()
    {
    	struct _timeb T;
    	_ftime(&T);
    	srand(time(0));
    	freopen("in.txt", "w", stdout);
    	int n=Random(10000),m=Random(10000);
    	printf("%d\n",n);
    	rep(i,1,n){
    		printf("%d ",Random(2)-1);
    	}
    	printf("\n%d\n",m);
    	rep(i,1,m){
    		int j=Random(n);
    		int k=Random(1);
    		if(j>k) swap(j,k);
    		printf("%lld %d %d\n",Random(2)-1,j,k);
    	}
    }
    

    AC代码(baoli)

    #include <bits/stdc++.h>
    #define debug(a) cout<<#a<<"="<<a<<"\n";
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    using namespace std;
    const long long N=2e5+7;
    int main(){
    	freopen("in.txt","r",stdin);
    	freopen("baoli.txt","w",stdout);
    	return 0;
    }
    

    代码(std)

    #include <bits/stdc++.h>
    #define debug(a) cout<<#a<<"="<<a<<"\n";
    #define rep(i,a,b) for(long long i=a;i<=b;++i)
    using namespace std;
    const long long N=2e5+7;
    int main(){
    	freopen("in.txt", "r", stdin);
    	freopen("std.txt", "w", stdout);
    	return 0;
    }
    

    oj入口

    洛谷入口

  • 通过的题目

  • 最近活动

题目标签

图论
37
动态规划
31
字符串
29
斜率优化
18
KMP
16
字符串哈希
14
单调队列/单调栈优化
12
网络流
10
模板
8
最大流
7
难度分类
7
费用流
6
最小割
5
上下界网络流
5
二分
4
AC自动机
4
决策单调性
3
数据结构
3
二分图最大匹配
3
hall定理
3