模板

缺省源

#include<bits/stdc++.h>
using namespace std;
#define il inline
#define int long long
bool St;
struct IO
{
	static const int Size=(1<<21);
	char buf[Size],*p1,*p2;
	int st[105],Top;
	~IO(){clear();}
	il void clear(){fwrite(buf,1,Top,stdout);Top=0;}
	il char gc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,Size,stdin),p1==p2)?EOF:*p1++;}
	il void pc(const char c){Top==Size&&(clear(),0);buf[Top++]=c;}
	il IO& operator >>(char& c){while(c=gc(),c==' ' || c=='\n' || c=='\r');return *this;}
	template<typename T>il IO& operator >>(T& x)
	{
		x=0;bool f=0;char c=gc();
		while(!isdigit(c)){if(c=='-') f=1;c=gc();}
		while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=gc();}
		f?x=-x:0;
		return *this;
	}
	il IO& operator >>(string& s)
	{
		s="";char c=gc();
		while(c==' ' || c=='\n' || c=='\r') c=gc();
		while(c!=' ' && c!='\n' && c!='\r' && c!=EOF) s+=c,c=gc();
		return *this;
	}
	il IO& operator <<(const char c){pc(c);return *this;}
	template<typename T> il IO& operator <<(T x)
	{
		if(x<0) pc('-'),x=-x;
		do st[++st[0]]=x%10,x/=10;while(x);
		while(st[0]) pc(st[st[0]--]+'0');
		return *this;
	}
	il IO& operator <<(const string s){for(auto c:s) pc(c);return *this;}
	il IO& operator <<(const char* c){for(int i=0;c[i];i++) pc(c[i]);return *this;}
} fin,fout;
bool Ed;
signed main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
//  cerr<<(&St-&Ed)/1024.0/1024.0<<"Mib\n";
    
	return 0;
}

数论

CRT

int a[11],b[11],n;
int mul(int x,int y,int mod)
{
	int ret=0;
	while(y)
	{
		if(y&1) ret=(ret+x)%mod;
		x=(x+x)%mod;
		y>>=1;
	}
	return ret;
}
int exgcd(int a,int b,int& x,int& y)
{
	if(b==0)
	{
		x=1,y=0;
		return a;
	}
	int d=exgcd(b,a%b,x,y);
	int t=x;
	x=y;
	y=t-a/b*y;
	return d;
}
int crt()
{
	int M=1,ret=0;
	for(int i=1;i<=n;i++) M*=a[i];
	for(int i=1;i<=n;i++)
	{
		int x,y,m=M/a[i];
		exgcd(m,a[i],x,y);
		x=(x%a[i]+a[i])%a[i];
		ret=(ret+mul(mul(m,x,M),b[i],M))%M;
	}
	return ret;
}
signed main()
{
	fin>>n;
	for(int i=1;i<=n;i++) fin>>a[i]>>b[i];
	fout<<crt();
	return 0;
}

excrt

const int N=100010;
int m[N],r[N],n;
int mul(int x,int y,int mod)
{
	int ret=0;
	while(y)
	{
		if(y&1) ret=(ret+x)%mod;
		x=(x+x)%mod;
		y>>=1;
	}
	return ret;
}
int exgcd(int a,int b,int& x,int& y)
{
	if(b==0)
	{
		x=1,y=0;
		return a;
	}
	int d=exgcd(b,a%b,x,y);
	int t=x;
	x=y;
	y=t-a/b*y;
	return d;
}
int excrt()
{
	int M=m[1],ans=r[1],t,y;
	for(int i=2;i<=n;i++)
	{
		int mi=m[i],res=((r[i]-ans)%mi+mi)%mi;
		int d=exgcd(M,mi,t,y);
		if(res%d!=0) return -1;
		t=mul(t,res/d,mi);
		ans+=t*M;
		M=mi/d*M;
		ans=(ans%M+M)%M;
	}
	return ans;
}
signed main()
{
	fin>>n;
	for(int i=1;i<=n;i++) fin>>m[i]>>r[i];
	fout<<excrt();
	return 0;
}

高斯消元法

#define il inline
double a[1010][1010],eps=1e-10;
int n;
bool gauss()
{
	int now=1,to;
	double t;
	for(int i=1;i<=n;i++)
	{
		for(to=now;to<=n;to++)
		{
			if(fabs(a[to][i])>eps) break;
		}
		if(to>n) break;
		if(to!=now) swap(a[to],a[now]);
		t=a[now][i];
		for(int j=1;j<=n+1;j++) a[now][j]/=t;
		for(int j=1;j<=n;j++)
		{
			if(j!=now)
			{
				t=a[j][i];
				for(int k=1;k<=n+1;k++)
				{
					a[j][k]-=t*a[now][k];
				}
			}
		}
		now++;
	}
	return now>n;
}
signed main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n+1;j++)
		{
			cin>>a[i][j];
		}
	}
	if(gauss())
	{
		for(int i=1;i<=n;i++)
		{
			printf("%.2lf\n",a[i][n+1]); 
		}
	}
	else printf("No Solution");
	return 0;
}

FFT

const int N=4000010;
const double pi=acos(-1.0);
int limit=1,r[N];
struct Complex
{
	double x,y;
} a[N],b[N];
Complex operator +(Complex x,Complex y){return {x.x+y.x,x.y+y.y};}
Complex operator -(Complex x,Complex y){return {x.x-y.x,x.y-y.y};}
Complex operator *(Complex x,Complex y){return {x.x*y.x-x.y*y.y,x.x*y.y+x.y*y.x};}
il void FFT(Complex* A,int type)
{
	for(int i=0;i<limit;i++) if(i<r[i]) swap(A[i],A[r[i]]);
	for(int mid=1;mid<limit;mid<<=1)
	{
		Complex Wn={cos(pi/mid),type*sin(pi/mid)};
		for(int len=(mid<<1),i=0;i<limit;i+=len)
		{
			Complex w={1,0};
			for(int j=0;j<mid;j++,w=w*Wn)
			{
				Complex x=A[i+j],y=w*A[i+j+mid];
				A[i+j]=x+y;
				A[i+j+mid]=x-y;
			}
		}
	}
}
signed main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	int n,m,tmp;fin>>n>>m;
	for(int i=0;i<=n;i++) fin>>tmp,a[i].x=tmp;
	for(int i=0;i<=m;i++) fin>>tmp,b[i].x=tmp;
	int l=0;
	while(limit<=n+m) limit<<=1,l++;
	for(int i=0;i<limit;i++) r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
	FFT(a,1);FFT(b,1);
	for(int i=0;i<limit;i++) a[i]=a[i]*b[i];
	FFT(a,-1);
	for(int i=0;i<=n+m;i++) fout<<(int)(a[i].x/limit+0.5)<<" ";
	return 0;
}

NTT

il int qpow(int x,int y)
{
	int ret=1;
	while(y)
	{
		if(y&1) ret=ret*x%mod;
		x=x*x%mod;y>>=1;
	}
	return ret;
}
int inv=qpow(3,mod-2);
il void NTT(int* A,int n,int type)
{
	for(int i=0;i<n;i++) if(r[i]>i) swap(A[i],A[r[i]]);
	for(int mid=1;mid<n;mid<<=1)
	{
		int Wn=qpow(type?3:inv,(mod-1)/(mid<<1));
		for(int len=(mid<<1),i=0;i<n;i+=len)
		{
			int w=1;
			for(int j=0;j<mid;j++,w=w*Wn%mod)
			{
				int x=A[i+j],y=w*A[i+j+mid]%mod;
				A[i+j]=(x+y)%mod;
				A[i+j+mid]=(x-y+mod)%mod;
			}
		}
	}
	if(!type)
	{
		int tmp=qpow(n,mod-2);
		for(int i=0;i<n;i++) A[i]=A[i]*tmp%mod;
	}
}

多项式乘法逆

const int N=400010,mod=998244353;
int w[N],ans[N],A[N],B[N],r[N];
il int qpow(int x,int y)
{
	int ret=1;
	while(y)
	{
		if(y&1) ret=ret*x%mod;
		x=x*x%mod;y>>=1;
	}
	return ret;
}
int inv=qpow(3,mod-2);
il void NTT(int* A,int n,int type)
{
	for(int i=0;i<n;i++) if(r[i]>i) swap(A[i],A[r[i]]);
	for(int mid=1;mid<n;mid<<=1)
	{
		int Wn=qpow(type?3:inv,(mod-1)/(mid<<1));
		for(int len=(mid<<1),i=0;i<n;i+=len)
		{
			int w=1;
			for(int j=0;j<mid;j++,w=w*Wn%mod)
			{
				int x=A[i+j],y=w*A[i+j+mid]%mod;
				A[i+j]=(x+y)%mod;
				A[i+j+mid]=(x-y+mod)%mod;
			}
		}
	}
	if(!type)
	{
		int tmp=qpow(n,mod-2);
		for(int i=0;i<n;i++) A[i]=A[i]*tmp%mod;
	}
}
il void Inv(int* a,int* b,int n)
{
	b[0]=qpow(a[0],mod-2);
	for(int lim=2;lim<=n;lim<<=1)
	{
//		fout<<lim<<"\n";
		int len=lim<<1;
		for(int i=0;i<lim;i++) A[i]=a[i],B[i]=b[i];
		for(int i=0;i<len;i++) r[i]=(r[i>>1]>>1)|((i&1)*lim);
		NTT(A,len,1);NTT(B,len,1);
		for(int i=0;i<len;i++) b[i]=B[i]*(2-A[i]*B[i]%mod+mod)%mod;
		NTT(b,len,0);
		for(int i=lim;i<len;i++) b[i]=0;
	}
}
signed main()
{
	int n;fin>>n;
	for(int i=0;i<n;i++) fin>>w[i];
	Inv(w,ans,n<<1);
	for(int i=0;i<n;i++) fout<<ans[i]<<" ";
	return 0;
}

多项式开根

const int N=400010,mod=998244353;
int w[N],ans[N],A[N],B[N],C[N],D[N],r[N];
il int qpow(int x,int y)
{
	int ret=1;
	while(y)
	{
		if(y&1) ret=ret*x%mod;
		x=x*x%mod;y>>=1;
	}
	return ret;
}
int inv2=qpow(2,mod-2),inv3=qpow(3,mod-2);
il void NTT(int* A,int n,int type)
{
	for(int i=0;i<n;i++) if(r[i]>i) swap(A[i],A[r[i]]);
	for(int mid=1;mid<n;mid<<=1)
	{
		int Wn=qpow(type?3:inv3,(mod-1)/(mid<<1));
		for(int len=(mid<<1),i=0;i<n;i+=len)
		{
			int w=1;
			for(int j=0;j<mid;j++,w=w*Wn%mod)
			{
				int x=A[i+j],y=A[i+j+mid]*w%mod;
				A[i+j]=(x+y)%mod;
				A[i+j+mid]=(x-y+mod)%mod;
			}
		}
	}
	if(!type)
	{
		int tmp=qpow(n,mod-2);
		for(int i=0;i<n;i++) A[i]=A[i]*tmp%mod;
	}
}
il void Inv(int* a,int* b,int n)
{
	b[0]=qpow(a[0],mod-2);
	int now=1;
	while(now<n)
	{
		now<<=1;
		int len=(now<<1);
		for(int i=0;i<now;i++) A[i]=a[i],B[i]=b[i];
		for(int i=0;i<len;i++) r[i]=(r[i>>1]>>1)|((i&1)*now);
		NTT(A,len,1);NTT(B,len,1);
		for(int i=0;i<len;i++) b[i]=B[i]*(2-B[i]*A[i]%mod+mod)%mod;
		NTT(b,len,0);
		for(int i=now;i<len;i++) b[i]=0;
	}
	for(int i=0;i<(n<<1);i++) A[i]=B[i]=0;
}
il void sqr(int* a,int* b,int n)
{
	b[0]=1;
	int now=1;
	while(now<n)
	{
		now<<=1;
		int len=(now<<1);
		for(int i=0;i<now;i++) C[i]=a[i];
		Inv(b,D,now);
		for(int i=0;i<len;i++) r[i]=(r[i>>1]>>1)|((i&1)*now);
		NTT(C,len,1);NTT(D,len,1);
		for(int i=0;i<len;i++) C[i]=C[i]*D[i]%mod;
		NTT(C,len,0);
		for(int i=0;i<now;i++) b[i]=inv2*(C[i]+b[i])%mod;
		for(int i=now;i<len;i++) b[i]=0;
	}
}
signed main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	int n;fin>>n;
	for(int i=0;i<n;i++) fin>>w[i];
	sqr(w,ans,n);
	for(int i=0;i<n;i++) fout<<ans[i]<<" ";
	return 0;
}

lucas

const int N=100010;
int n,m,mod,jc[N],fjc[N];
int C(int x,int y,int p)
{
	if(x<y) return 0;
	return jc[x]*fjc[y]%p*fjc[x-y]%p;
}
int lucas(int x,int y,int p)
{
	if(y==0) return 1;
	return lucas(x/p,y/p,p)*C(x%p,y%p,p)%p;
}
int qpow(int x,int y,int p)
{
	int ret=1;
	while(y)
	{
		if(y&1) ret=ret*x%p;
		x=x*x%p;
		y>>=1;
	}
	return ret;
}
signed main()
{
	int t;
	fin>>t;
	while(t--)
	{
		fin>>n>>m>>mod;
		jc[0]=1;
		for(int i=1;i<mod;i++) jc[i]=jc[i-1]*i%mod;
		fjc[mod-1]=qpow(jc[mod-1],mod-2,mod);
		for(int i=mod-2;i>=0;i--) fjc[i]=fjc[i+1]*(i+1)%mod;
		fout<<lucas(n+m,n,mod)<<"\n";
	}
	return 0;
}

exlucas

#define ll __int128
ll m[1000010],r[1000010];
int cnt;
ll exgcd(ll a,ll b,ll &x,ll &y)
{
	if(b==0)
	{
		x=1,y=0;
		return a;
	}
	ll d=exgcd(b,a%b,x,y);
	int t=x;
	x=y;
	y=t-a/b*y;
	return d;
}
ll inv(ll a,ll b)
{
	ll x,y;
	exgcd(a,b,x,y);
	return (x%b+b)%b;
}
ll qpow_mod(ll a,ll b,ll mod)
{
	ll ret=1;
	while(b)
	{
		if(b&1) ret=ret*a%mod;
		a=a*a%mod;
		b>>=1;
	}
	return ret;
}
ll fac_mod(ll n,ll p,ll pk)
{
	if(!n) return 1;
	ll ret=1;
	for(ll i=1;i<=pk;i++) if(i%p) ret=ret*i%pk;
	ret=qpow_mod(ret,n/pk,pk);
	for(ll i=1;i<=n%pk;i++) if(i%p) ret=ret*i%pk;
	return ret*fac_mod(n/p,p,pk)%pk;
}
ll C_mod(ll n,ll m,ll p,ll pk)
{
	ll x=0,y=0,z=0;
	for(ll i=p;i<=n;i*=p) x+=n/i;
	for(ll i=p;i<=m;i*=p) y+=m/i;
	for(ll i=p;i<=n-m;i*=p) z+=(n-m)/i;
	return ((fac_mod(n,p,pk)*inv(fac_mod(m,p,pk),pk)%pk)*inv(fac_mod(n-m,p,pk),pk)%pk)*qpow_mod(p,x-y-z,pk)%pk;
}
ll crt(ll m[],ll r[],int n)
{
	ll M=1,res=0;
	for(int i=1;i<=n;i++) M*=m[i];
	for(int i=1;i<=n;i++)
	{
		ll mod=M/m[i];
		res=(res+(mod*inv(mod,m[i])%M)*r[i]%M)%M;
	}
	return res;
}
ll exlucas(ll n,ll M,ll p)
{
	for(ll i=2;i*i<=p;i++)
	{
		if(p%i==0)
		{
			ll pk=1;
			while(p%i==0)
			{
				pk*=i;
				p/=i;
			}
			m[++cnt]=pk;
			r[cnt]=C_mod(n,M,i,pk);
		}
	}
	if(p!=1)
	{
		cnt++;
		m[cnt]=p;
		r[cnt]=C_mod(n,M,p,p);
	}
	return crt(m,r,cnt);
}
int main()
{
	ll n,m,p; fin>>n>>m>>p;
	fout<<exlucas(n,m,p);
	return 0;
}

杜教筛

const int N=2e6+10;
ll mu[N],phi[N];
struct hashmap
{
	static const int MOD=1e7+19;
	int h[MOD],cnt;
	struct hashnode
	{
		int nxt;
		ll a,b;
	} e[N];
	void change(ll x,ll y)
	{
		int c=x%MOD;
		for(int i=h[c];i;i=e[i].nxt)
		{
			if(e[i].a==x)
			{
				e[i].b=y;
				return;
			}
		}
		e[++cnt]={h[c],x,y},h[c]=cnt;
	}
	bool find(ll x)
	{
		int c=x%MOD;
		for(int i=h[c];i;i=e[i].nxt)
		{
			if(e[i].a==x) return true;
		}
		return false;
	}
	ll operator [](ll x)
	{
		int c=x%MOD;
		for(int i=h[c];i;i=e[i].nxt)
		{
			if(e[i].a==x) return e[i].b;
		}
		return 0;
	}
} smu,sphi;
int vis[N],p[N],cnt;
void init()
{
	mu[1]=1;phi[1]=1;
	for(int i=2;i<=N-10;i++)
	{
		if(!vis[i])
		{
			p[++cnt]=i;
			mu[i]=-1;phi[i]=i-1;
		}
		for(int j=1;i*p[j]<=N-10;j++)
		{
			vis[i*p[j]]=1;
			if(i%p[j]==0)
			{
				phi[i*p[j]]=phi[i]*p[j];
				break;
			}
			phi[i*p[j]]=phi[i]*(p[j]-1);
			mu[i*p[j]]=-mu[i];
		}
	}
	for(int i=2;i<=N-10;i++) mu[i]+=mu[i-1];
	for(int i=2;i<=N-10;i++) phi[i]+=phi[i-1];
}
ll get_sphi(ll n)
{
	if(n<=N-10)	return phi[n];
	if(sphi.find(n)) return sphi[n];
	ll ret=1ll*(n+1)*n/2;
	for(ll l=2,r;l<=n;l=r+1)
	{
		r=n/(n/l);
		ret-=1ll*(r-l+1)*get_sphi(n/l);
	}
	sphi.change(n,ret);
	return ret;
}
ll get_smu(ll n)
{
	if(n<=N-10)	return mu[n];
	if(smu.find(n)) return smu[n];
	ll ret=1;
	for(ll l=2,r;l<=n;l=r+1)
	{
		r=n/(n/l);
		ret-=1ll*(r-l+1)*get_smu(n/l);
	}
	smu.change(n,ret);
	return ret;
}
signed main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	init();
	int t;fin>>t;
	while(t--)
	{
		ll n;fin>>n;
		fout<<get_sphi(n)<<" "<<get_smu(n)<<"\n";
	}
	return 0;
}

自适应辛普森积分

const double eps=1e-6;
double a,b,c,d;
double F(double x)
{
	return (c*x+d)/(a*x+b);
}
il double Simpson(double l,double r)
{
	double mid=(l+r)/2;
	return (r-l)/6*(F(l)+F(r)+4*F(mid));
}
il double asr(double l,double r,double lst,double eps,int dep)
{
	double mid=(l+r)/2;
	double Lv=Simpson(l,mid),Rv=Simpson(mid,r),t;
	if(dep<=0 && fabs(t=Lv+Rv-lst)<=15*eps) return Lv+Rv+t/15;
	return asr(l,mid,Lv,eps/2,dep-1)+asr(mid,r,Rv,eps/2,dep-1);
}
signed main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	double l,r;cin>>a>>b>>c>>d>>l>>r;
	cout<<fixed<<setprecision(6)<<asr(l,r,Simpson(l,r),eps,10);
	return 0;
}

Min_25筛

const int N=200010,mod=1e9+7;
int n,m,vis[N],prime[N],cnt,Id1[N],Id2[N],val[N],tot,g1[N],g2[N];
il int get_id(int x){return x<=m?Id1[x]:Id2[n/x];}
il int qpow(int x,int y)
{
	int ret=1;
	while(y)
	{
		if(y&1) ret=ret*x%mod;
		x=x*x%mod;y>>=1;
	}
	return ret;
}
int inv2=qpow(2,mod-2),inv6=qpow(6,mod-2);
il void init()
{
	for(int i=2;i<=m;i++)
	{
		if(!vis[i])
		{
			prime[++cnt]=i;
			for(int j=i+i;j<=m;j+=i) vis[j]=1;
		}
	}
	for(int l=1,r=0;l<=n;l=r+1)
	{
		r=n/(n/l);
		int tmp=n/l;
		val[++tot]=tmp;
		if(tmp<=m) Id1[tmp]=tot;
		else Id2[n/tmp]=tot;
		tmp%=mod;
		g1[tot]=((tmp+1)*tmp%mod*inv2%mod+mod-1)%mod;
		g2[tot]=((tmp+1)*tmp%mod*(2*tmp+1)%mod*inv6%mod+mod-1)%mod;
	}
	for(int j=1;j<=cnt;j++)
	{
		for(int i=1;i<=tot&&val[i]>=prime[j]*prime[j];i++)
		{
			int id1=get_id(val[i]/prime[j]),id2=get_id(prime[j-1]);
			g1[i]-=prime[j]*(g1[id1]-g1[id2])%mod;
			g2[i]-=prime[j]*prime[j]%mod*(g2[id1]-g2[id2])%mod;
			g1[i]=(g1[i]%mod+mod)%mod;
			g2[i]=(g2[i]%mod+mod)%mod;
		}
	}
}
il int F(int x){x%=mod;return (x*x-x+mod)%mod;}
il int S(int N,int j)
{
	if(prime[j]>N) return 0;
//	cout<<N<<" "<<prime[j]<<"\n";
	int id1=get_id(N),id2=get_id(prime[j]);
	int ret=(g2[id1]-g1[id1])-(g2[id2]-g1[id2]);
	ret=(ret%mod+mod)%mod;
	for(int k=j+1;k<=cnt && prime[k]*prime[k]<=N;k++)
	{
		for(int num=prime[k],e=1;num<=N;num*=prime[k],e++)
		{
			ret=(ret+F(num)*(S(N/num,k)+(e!=1)))%mod;
		}
	}
	return ret;
}
signed main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	fin>>n;m=sqrt(n);
	init();
	fout<<(S(n,0)+1)%mod<<"\n";
	return 0;
}

求原根

const int N=1000010;
int phi[N],prime[N],cnt,vis[N];
vector<int> root,p;
il bool exist_root(int n)
{
	if(n==2 || n==4) return 1;
	if(n%2==0)
	{
		n/=2;
		if(n%2==0) return 0;
	}
	int cnt=0,tmp=n;
	for(int i=2;i*i<=n;i++)
	{
		if(tmp%i==0)
		{
			cnt++;
			while(tmp%i==0) tmp/=i;
		}
	}
	if(tmp!=1) cnt++;
	return cnt==1;
}
il int qpow(int x,int y,int mod)
{
	int ret=1;
	while(y)
	{
		if(y&1) ret=ret*x%mod;
		x=x*x%mod;y>>=1;
	}
	return ret;
}
il int get_minroot(int n)
{
	vector<int> ().swap(p);
	int tmp=phi[n];
	for(int i=2;i*i<=phi[n];i++)
	{
		if(tmp%i==0)
		{
			p.push_back(i);
			while(tmp%i==0) tmp/=i;
		}
	}
	if(tmp!=1) p.push_back(tmp);
	for(int i=1;i<=n;i++)
	{
		int fl=1;
		if(qpow(i,phi[n],n)!=1) continue;
		for(int j:p)
		{
			if(qpow(i,phi[n]/j,n)==1)
			{
				fl=0;
				break;
			}
		}
		if(fl) return i;
	}
	return -1;
}
signed main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	int t;fin>>t;
	phi[1]=1;
	for(int i=2;i<=1e6;i++)
	{
		if(!vis[i]) phi[i]=i-1,prime[++cnt]=i;
		for(int j=1;j<=cnt;j++)
		{
			int tmp=prime[j]*i;
			if(tmp>1e6) break;
			vis[tmp]=1;
			if(i%prime[j]==0)
			{
				phi[tmp]=phi[i]*prime[j];
				break;
			}
			phi[tmp]=phi[i]*(prime[j]-1);
		}
	}
	while(t--)
	{
		int n,d;fin>>n>>d;
		vector<int> ().swap(root);
		if(!exist_root(n)) fout<<0<<"\n\n";
		else
		{
			int g=get_minroot(n);
			for(int i=1;i<=phi[n];i++)
			{
				if(__gcd(i,phi[n])!=1) continue;
				root.push_back(qpow(g,i,n));
			}
			sort(root.begin(),root.end());
			fout<<root.size()<<"\n";
			for(int i=1;i<=(int)root.size()/d;i++)
			{
				fout<<root[i*d-1]<<" ";
			}
			fout<<"\n";
		}
	}
	return 0;
}

数据结构

普通莫队

int cnt[50010],a[50010],b[50010],x,res,ans[50010];
struct question
{
	int l,r,idx;
} q[50010];
bool cmp(question x,question y)
{
	if(b[x.l]!=b[y.l])
	{
		return b[x.l]<b[y.l];
	}
	if(b[x.l]&1) return x.r<y.r;
	else return x.r>x.r;
}
void add(int i)
{
	res+=cnt[a[i]]*2+1;
	cnt[a[i]]++;
}
void del(int i)
{
	res-=cnt[a[i]]*2-1;
	cnt[a[i]]--;
}
int main()
{
	int n,m,k;
	cin>>n>>m>>k;
	x=sqrt(n);
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=n;i++) b[i]=(i-1)/x+1;
	for(int i=1;i<=m;i++)
	{
		cin>>q[i].l>>q[i].r;
		q[i].idx=i;
	}
	sort(q+1,q+1+m,cmp);
	int L=1,R=1;
	res=1;
	cnt[a[1]]=1;
	for(int i=1;i<=m;i++)
	{
		while(L>q[i].l) add(--L);
		while(R<q[i].r) add(++R);
		while(L<q[i].l) del(L++);
		while(R>q[i].r) del(R--);
		ans[q[i].idx]=res;
	}
	for(int i=1;i<=m;i++) cout<<ans[i]<<"\n";
	return 0;
}

带修莫队

const int N=150010;
int b[N],a[N],cntq,tim,B,cnt[1000010],ret,ans[N];
struct qwq
{
	int tim,idx,l,r;
} q[N];
struct node
{
	int pos,val;
} c[N];
bool cmp(qwq x,qwq y)
{
	return tie(b[x.l],b[x.r],x.tim)<tie(b[y.l],b[y.r],y.tim);
}
void add(int x)
{
	if(cnt[a[x]]==0) ret++;
	cnt[a[x]]++;
}
void del(int x)
{
	if(cnt[a[x]]==1) ret--;
	cnt[a[x]]--;
}
void change(int x,int l,int r)
{
	int idx=c[x].pos;
	if(l<=idx && idx<=r)
	{
		if(cnt[a[idx]]==1) ret--;
		cnt[a[idx]]--;
		if(cnt[c[x].val]==0) ret++;
		cnt[c[x].val]++;
	}
	swap(c[x].val,a[idx]);
}
signed main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	int n,m;fin>>n>>m;B=pow(n,0.66);
	for(int i=1;i<=n;i++) fin>>a[i];
	for(int i=1;i<=n;i++) b[i]=(i-1)/B+1;
	while(m--)
	{
		char op;int x,y;fin>>op>>x>>y;
		if(op=='Q')
		{
			cntq++;
			q[cntq]={tim,cntq,x,y};
		}
		else
		{
			tim++;
			c[tim]={x,y};
		}
	}
	sort(q+1,q+1+cntq,cmp);
	int L=1,R=0,now=0;
	for(int i=1;i<=cntq;i++)
	{
		while(R<q[i].r) add(++R);
		while(L>q[i].l) add(--L);
		while(R>q[i].r) del(R--);
		while(L<q[i].l) del(L++);
		while(now<q[i].tim) change(++now,q[i].l,q[i].r);
		while(now>q[i].tim) change(now--,q[i].l,q[i].r);
		ans[q[i].idx]=ret;
	}
	for(int i=1;i<=cntq;i++) fout<<ans[i]<<"\n";
	return 0;
}

WBLT

const int N=100010;
const double Alpha=0.3;
int pool[N],top,tot,son[N][2],siz[N],val[N],rt;
void push_up(int x)
{
	siz[x]=siz[son[x][0]]+siz[son[x][1]];
	val[x]=val[son[x][1]];
}
int new_node()
{
	int x=top?pool[top--]:++tot;
	son[x][0]=son[x][1]=val[x]=siz[x]=0;
	return x;
}
void del_node(int& x)
{
	pool[++top]=x;
	x=0;
}
int new_leaf(int v)
{
	int x=new_node();
	val[x]=v;siz[x]=1;
	return x;
}
int join(int x,int y)
{
	int z=new_node();
	son[z][0]=x;son[z][1]=y;
	push_up(z);
	return z;
}
auto cut(int& z)
{
	int x=son[z][0],y=son[z][1];
	del_node(z);
	return make_pair(x,y);
}
void rotate(int& x,int r)
{
	int a,b,c,d;
	tie(a,b)=cut(x);
	if(r)
	{
		tie(c,d)=cut(b);
		x=join(join(a,c),d);
	}
	else
	{
		tie(c,d)=cut(a);
		x=join(c,join(d,b));
	}
}
bool too_heavy(int sx,int sy)
{
	return sy<Alpha*(sx+sy);
}
bool need_two(int x,bool r)
{
	return siz[son[x][!r]]>siz[x]/(2-Alpha);
}
void balance(int& x)
{
	if(siz[x]==1) return;
	bool r=siz[son[x][1]]>siz[son[x][0]];
	if(!too_heavy(siz[son[x][r]],siz[son[x][!r]])) return;
	if(need_two(son[x][r],r)) rotate(son[x][r],!r);
	rotate(x,r);
}
void insert(int& x,int v)
{
	if(!x)
	{
		x=new_leaf(v);
		return;
	}
	else if(siz[x]==1)
	{
		bool r=v>=val[x];
		son[x][r]=new_leaf(v);
		son[x][!r]=new_leaf(val[x]);
		push_up(x);
		return;
	}
	else
	{
		if(v<=val[son[x][0]]) insert(son[x][0],v);
		else insert(son[x][1],v);
		push_up(x);
		balance(x);
	}
}
void remove(int& x,int v)
{
	if(siz[x]==1) del_node(x);
	else
	{
		bool r=v>val[son[x][0]];
		remove(son[x][r],v);
		if(!siz[son[x][r]]) x=son[x][!r];
		else push_up(x),balance(x);
	}
}
int get_cnt(int x,int w)
{
	if(!x) return 0;
	if(siz[x]==1) return val[x]<w;
	if(w<=val[son[x][0]]) return get_cnt(son[x][0],w);
	else return siz[son[x][0]]+get_cnt(son[x][1],w);
}
int get_num(int x,int w)
{
	if(siz[x]==1) return val[x];
	if(w<=siz[son[x][0]]) return get_num(son[x][0],w);
	else return get_num(son[x][1],w-siz[son[x][0]]);
}
signed main()
{
//	freopen("P3369_5.in","r",stdin);
//	freopen("chj.out","w",stdout);
	int q;fin>>q;
	while(q--)
	{
		int op,x;fin>>op>>x;
		if(op==1) insert(rt,x);
		else if(op==2) remove(rt,x);
		else if(op==3) fout<<get_cnt(rt,x)+1<<"\n";
		else if(op==4) fout<<get_num(rt,x)<<"\n";
		else if(op==5) fout<<get_num(rt,get_cnt(rt,x))<<"\n";
		else fout<<get_num(rt,get_cnt(rt,x+1)+1)<<"\n";
	}
	return 0;
}

区间WBLT

const int N=100010;
const double Alpha=0.292; 
int lazy[N<<1],val[N<<1],siz[N<<1],son[N<<1][2],pool[N<<1],top,tot,rt;
il void push_up(int x)
{
	siz[x]=siz[son[x][0]]+siz[son[x][1]];
}
il int new_node()
{
	int x=top?pool[top--]:++tot;
	siz[x]=lazy[x]=son[x][0]=son[x][1]=val[x]=0;
	return x;
}
il void del_node(int& x)
{
	pool[++top]=x;x=0;
}
il int new_leaf(int v)
{
	int x=new_node();
	val[x]=v;siz[x]=1;
	return x;
}
il int join(int x,int y)
{
	int z=new_node();
	son[z][0]=x;son[z][1]=y;
	push_up(z);
	return z;
}
il void lazy_reverse(int x)
{
	if(!x) return;
	lazy[x]^=1;
	swap(son[x][0],son[x][1]);
}
il void push_down(int x)
{
	if(lazy[x])
	{
		lazy_reverse(son[x][0]);
		lazy_reverse(son[x][1]);
		lazy[x]=0;
	}
}
il auto cut(int& x)
{
	push_down(x);
	int y=son[x][0],z=son[x][1];
	del_node(x);
	return make_pair(y,z);
}
il void rotate(int& x,bool r)
{
	int a,b,c,d;
	tie(a,b)=cut(x);
	if(r)
	{
		tie(c,d)=cut(b);
		x=join(join(a,c),d);
	}
	else
	{
		tie(c,d)=cut(a);
		x=join(c,join(d,b));
	}
}
il bool too_heavy(int sx,int sy)
{
	return sy<Alpha*(sx+sy);
}
il bool need_two(int x,bool r)
{
	return siz[son[x][!r]]>siz[x]/(2-Alpha);
}
il void balance(int& x)
{
	if(siz[x]==1) return;
	push_down(x);
	bool r=siz[son[x][1]]>siz[son[x][0]];
	if(!too_heavy(siz[son[x][r]],siz[son[x][!r]])) return;
	push_down(son[x][r]);
	if(need_two(son[x][r],r))
	{
		push_down(son[son[x][r]][!r]);
		rotate(son[x][r],!r);
	}
	rotate(x,r);
}
il int merge(int x,int y)
{
	if(!x || !y) return x|y;
	int a,b;
	if(too_heavy(siz[x],siz[y]))
	{
		tie(a,b)=cut(x);
		x=join(a,merge(b,y));
		balance(x);
		return x;
	}
	else if(too_heavy(siz[y],siz[x]))
	{
		tie(a,b)=cut(y);
		x=join(merge(x,a),b);
		balance(x);
		return x;
	}
	else return join(x,y);
}
il pair<int,int> split(int x,int k)
{
	if(!x) return {0,0};
	if(!k) return {0,x};
	if(k==siz[x]) return {x,0};
	int a,b;
	tie(a,b)=cut(x);
	if(k<=siz[a])
	{
		int ll,rr;
		tie(ll,rr)=split(a,k);
		return {ll,merge(rr,b)};
	}
	else
	{
		int ll,rr;
		k-=siz[a];
		tie(ll,rr)=split(b,k);
		return {merge(a,ll),rr};
	}
}
il void reverse(int l,int r)
{
	int ll,rr;
	tie(ll,rr)=split(rt,r);
	tie(ll,rt)=split(ll,l-1);
	lazy_reverse(rt);
	rt=merge(merge(ll,rt),rr);
}
il int build(int l,int r)
{
	if(l==r) return new_leaf(l);
	int mid=(l+r)>>1;
	return join(build(l,mid),build(mid+1,r));
}
il void print(int x)
{
	if(siz[x]==1)
	{
		fout<<val[x]<<" ";
		return;
	}
	push_down(x);
	print(son[x][0]);
	print(son[x][1]);
}
signed main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	int n,m,l,r;fin>>n>>m;
	rt=build(1,n);
	while(m--)
	{
		fin>>l>>r;
		reverse(l,r);
	}
	print(rt);
	return 0;
}

可持久化WBLT

const int N=500010;
const double Alpha=0.292;
int rt[N],pool[N<<5],tp,tot;
struct node
{
	int son[2],val,siz,use;
} t[N<<5];
il int new_node(int x)
{
	int id=tp?pool[tp--]:++tot;
	t[id].use=t[id].siz=1;
	t[id].val=x;
	t[id].son[0]=t[id].son[1]=0;
	return id;
}
il void push_up(int id)
{
	t[id].siz=t[t[id].son[0]].siz+t[t[id].son[1]].siz;
	t[id].val=t[t[id].son[1]].val;
}
il void del_node(int& id)
{
	pool[++tp]=id;
	id=0;
}
il int join(int x,int y)
{
	int z=new_node(0);
	t[z].son[0]=x,t[z].son[1]=y;
	push_up(z);
	return z;
}
il void clone(int x,int y)
{
	t[x].son[0]=t[y].son[0];
	t[x].son[1]=t[y].son[1];
	t[x].siz=t[y].siz;
	t[x].val=t[y].val;
	if(t[x].son[0])
	{
		t[t[x].son[0]].use++;
		t[t[x].son[1]].use++;
	}
}
il void refresh(int& x)
{
	if(t[x].use==1 || !x) return;
	t[x].use--;
	int y=x;x=new_node(0);
	clone(x,y);
}
il auto cut(int& x)
{
	refresh(x);
	int y=t[x].son[0],z=t[x].son[1];
	del_node(x);
	return make_pair(y,z);
}
il void rotate(int& x,bool r)
{
	int a,b,c,d;
	tie(a,b)=cut(x);
	if(r)
	{
		tie(c,d)=cut(b);
		x=join(join(a,c),d);
	}
	else
	{
		tie(c,d)=cut(a);
		x=join(c,join(d,b));
	}
}
il bool too_heavy(int sx,int sy)
{
	return sy<Alpha*(sx+sy);
}
il bool need_two(int x,bool r)
{
	return t[t[x].son[!r]].siz>=t[x].siz/(2-Alpha);
}
il void balance(int& x)
{
	if(!t[x].son[0]) return;
	refresh(x);
	bool r=t[t[x].son[1]].siz>t[t[x].son[0]].siz;
	if(!too_heavy(t[t[x].son[r]].siz,t[t[x].son[!r]].siz)) return;
	refresh(t[x].son[r]);
	if(need_two(t[x].son[r],r))
	{
//		refresh(t[t[x].son[r]].son[!r]);
		rotate(t[x].son[r],!r);
	}
	rotate(x,r);
}
il void ins(int& x,int v)
{
	refresh(x);
	if(!x) x=new_node(v);
	else if(!t[x].son[0])
	{
		bool r=v>t[x].val;
		t[x].son[r]=new_node(v);
		t[x].son[!r]=new_node(t[x].val);
		push_up(x);
	}
	else
	{
		bool r=v>t[t[x].son[0]].val;
		ins(t[x].son[r],v);
		push_up(x);
		balance(x);
	}
}
il void del(int& x,int v)
{
	refresh(x);
	if(!x) return;
	if(!t[x].son[0])
	{
		if(t[x].val==v) del_node(x);
	}
	else
	{
		bool r=v>t[t[x].son[0]].val;
		del(t[x].son[r],v);
		if(!t[x].son[r]) x=t[x].son[!r];
		else push_up(x),balance(x);
	}
}
il int query_num(int x,int v)
{
	if(!t[x].son[0]) return t[x].val;
	else
	{
		int w=t[t[x].son[0]].siz;
		if(v<=w) return query_num(t[x].son[0],v);
		else return query_num(t[x].son[1],v-w);
	}
}
il int query_sum(int x,int v)
{
//	if(!x) return 0;
	if(!t[x].son[0]) return t[x].val<v;
	else
	{
		int w=t[t[x].son[0]].val;
		if(w<v) return t[t[x].son[0]].siz+query_sum(t[x].son[1],v);
		else return query_sum(t[x].son[0],v);
	}
}
signed main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	int q;fin>>q;
	for(int u=1;u<=q;u++)
	{
		int v,op,x;fin>>v>>op>>x;
		t[rt[u]=rt[v]].use++;
		if(op==1) ins(rt[u],x);
		else if(op==2) del(rt[u],x);
		else if(op==3) fout<<query_sum(rt[u],x)+1<<"\n";
		else if(op==4) fout<<query_num(rt[u],x)<<"\n";
		else if(op==5)
		{
			int val=query_sum(rt[u],x);
			if(val==0) fout<<"-2147483647\n";
			else fout<<query_num(rt[u],val)<<"\n";
		}
		else if(op==6)
		{
			int val=query_sum(rt[u],x+1);
			if(val==t[rt[u]].siz) fout<<"2147483647\n";
			else fout<<query_num(rt[u],val+1)<<"\n";
		}
	}
	return 0;
}

可持久化区间WBLT

const int N=200010;
const double Alpha=0.292;
int use[N*70],lazy[N*70],siz[N*70],pool[N*70],son[N*70][2],top,tot,rt[N];
LL sum[N*70];
il void push_up(int x)
{
	if(!son[x][0]) return;
	sum[x]=sum[son[x][0]]+sum[son[x][1]];
	siz[x]=siz[son[x][0]]+siz[son[x][1]];
}
il int new_node(int v)
{
	int x=top?pool[top--]:++tot;
	siz[x]=use[x]=1;sum[x]=v;
	lazy[x]=son[x][0]=son[x][1]=0;
	return x;
}
il void del_node(int& x) {pool[++top]=x;x=0;}
il int join(int x,int y)
{
	int z=new_node(0);
	son[z][0]=x;son[z][1]=y;
	push_up(z);
	return z;
}
il void refresh(int& x)
{
	if(!x || use[x]<=1) return;
	use[x]--;
	int y=x;x=new_node(0);
	sum[x]=sum[y];
	siz[x]=siz[y];
	son[x][0]=son[y][0];
	son[x][1]=son[y][1];
	lazy[x]=lazy[y];
	if(son[x][0])
	{
		use[son[x][0]]++;
		use[son[x][1]]++;
	}
}
il void lazy_reverse(int& x)
{
	if(!son[x][0]) return;
	refresh(x);
	lazy[x]^=1;
}
il void push_down(int x)
{
	if(!lazy[x] || !son[x][0]) return;
	lazy_reverse(son[x][0]);lazy_reverse(son[x][1]);
	swap(son[x][0],son[x][1]);
	lazy[x]=0;
}
il auto cut(int& x)
{
	refresh(x);
	push_down(x);
	int y=son[x][0],z=son[x][1];
	del_node(x);
	return make_pair(y,z);
}
il void rotate(int& x,bool r)
{
	int a,b,c,d;
	tie(a,b)=cut(x);
	if(r)
	{
		tie(c,d)=cut(b);
		x=join(join(a,c),d);
	}
	else
	{
		tie(c,d)=cut(a);
		x=join(c,join(d,b));
	}
}
il bool too_heavy(int sx,int sy)
{
	return sy<Alpha*(sx+sy);
}
il bool need_two(int x,bool r)
{
	return siz[son[x][!r]]>siz[x]/(2-Alpha);
}
il void balance(int& x)
{
	if(!son[x][0]) return;
	refresh(x);
	push_down(x);
	bool r=siz[son[x][1]]>siz[son[x][0]];
	if(!too_heavy(siz[son[x][r]],siz[son[x][!r]])) return;
	refresh(son[x][r]);
	push_down(son[x][r]);
	if(need_two(son[x][r],r))
	{
		refresh(son[son[x][r]][!r]);
		push_down(son[son[x][r]][!r]);
		rotate(son[x][r],!r);
	}
	rotate(x,r);
}
il void add(int& x,int k,int v)
{
	refresh(x);
	push_down(x);
	if(!son[x][0])
	{
		son[x][0]=new_node(v);
		son[x][1]=new_node(sum[x]);
		push_up(x);
		return;
	}
	else
	{
		if(k<=siz[son[x][0]]) add(son[x][0],k,v);
		else add(son[x][1],k-siz[son[x][0]],v);
		push_up(x);
		balance(x);
	}
}
il void del(int& x,int k)
{
	refresh(x);
	push_down(x);
	if(!son[x][0])
	{
		del_node(x);
		return;
	}
	else
	{
		bool r=k>siz[son[x][0]];
		if(r) k-=siz[son[x][0]];
		del(son[x][r],k);
		if(!son[x][r]) x=son[x][!r];
		push_up(x);
		balance(x);
	}
}
il int merge(int x,int y)
{
	if(!x || !y) return x|y;
	int a,b;
	if(too_heavy(siz[x],siz[y]))
	{
		tie(a,b)=cut(x);
		x=join(a,merge(b,y));
		balance(x);
		return x;
	}
	else if(too_heavy(siz[y],siz[x]))
	{
		tie(a,b)=cut(y);
		x=join(merge(x,a),b);
		balance(x);
		return x;
	}
	else return join(x,y);
}
il pair<int,int> split(int x,int k)
{
	if(!x) return {0,0};
	if(!k) return {0,x};
	if(k==siz[x]) return {x,0};
	int a,b,ll,rr;
	tie(a,b)=cut(x);
	if(k<=siz[a])
	{
		tie(ll,rr)=split(a,k);
		return {ll,merge(rr,b)};
	}
	else
	{
		k-=siz[a];
		tie(ll,rr)=split(b,k);
		return {merge(a,ll),rr};
	}
}
il void reverse(int& x,int l,int r)
{
	int ll,rr;
	tie(ll,rr)=split(x,r);
	tie(ll,x)=split(ll,l-1);
	refresh(x);
	lazy_reverse(x);
	x=merge(merge(ll,x),rr);
}
il LL query_sum(int& x,int l,int r)
{
	int ll,rr;
	LL ret=0;
	tie(ll,rr)=split(x,r);
	tie(ll,x)=split(ll,l-1);
	ret=sum[x];
	x=merge(merge(ll,x),rr);
	return ret;
}
signed main()
{
//	freopen("P5055_7.in","r",stdin);
//	freopen("chj.out","w",stdout);
	int n;fin>>n;
	LL lstans=0;
	rt[0]=new_node(0);
	for(int i=1;i<=n;i++)
	{
		int v,op;fin>>v>>op;
		rt[i]=rt[v];use[rt[i]]++;
		if(op==1)
		{
			LL p,x;fin>>p>>x;
			p^=lstans;x^=lstans;
			add(rt[i],p+1,x);
		}
		else if(op==2)
		{
			LL p;fin>>p;p^=lstans;
			del(rt[i],p);
		}
		else if(op==3)
		{
			LL l,r;fin>>l>>r;
			l^=lstans;r^=lstans;
			reverse(rt[i],l,r);
		}
		else
		{
			LL l,r;fin>>l>>r;
			l^=lstans;r^=lstans;
			fout<<(lstans=query_sum(rt[i],l,r))<<"\n";
		}
	}
	return 0;
}

splay

const int N=100010;
int rt=0,son[N][2],fa[N],siz[N],cnt[N],val[N],tot;
int dir(int x){return x==son[fa[x]][1];}
void push_up(int x){siz[x]=siz[son[x][0]]+siz[son[x][1]]+cnt[x];}
void rotate(int x)
{
	int y=fa[x],z=fa[y];
	bool r=dir(x);
	son[y][r]=son[x][!r];
	son[x][!r]=y;
	if(z) son[z][dir(y)]=x;
	if(son[y][r]) fa[son[y][r]]=y;
	fa[y]=x;fa[x]=z;
	push_up(y);push_up(x);
}
void splay(int& z,int x)
{
	int w=fa[z];
	for(int y;(y=fa[x])!=w;rotate(x))
	{
		if(fa[y]!=w) rotate((dir(x)==dir(y))?y:x);
	}
	z=x;
}
void find(int& z,int v)
{
	int x=z,y=fa[x];
	while(1)
	{
		if(val[x]==v) break;
		y=x;
		x=son[x][v>val[x]];
		if(!x) break;
	}
	splay(z,x?x:y);
}
void loc(int& z,int k)
{
	int x=z;
	while(1)
	{
		if(siz[son[x][0]]>=k) x=son[x][0];
		else if(siz[son[x][0]]+cnt[x]>=k) break;
		else
		{
			k-=siz[son[x][0]]+cnt[x];
			x=son[x][1];
		}
	}
	splay(z,x);
}
int get_num(int x)
{
	if(x>siz[rt]) return -1;
	loc(rt,x);
	return val[rt];
}
int merge(int x,int y)
{
	if(!x || !y) return x|y;
	loc(y,1);
	son[y][0]=x;
	fa[x]=y;
	push_up(y);
	return y;
}
void ins(int v)
{
	int x=rt,y=0;
	while(1)
	{
		if(val[x]==v) break;
		y=x;x=son[x][v>val[x]];
		if(x==0) break;
	}
	if(x)
	{
		cnt[x]++;
		siz[x]++;
	}
	else
	{
		x=++tot;
		val[x]=v;
		cnt[x]=siz[x]=1;
		fa[x]=y;
		if(y) son[y][v>val[y]]=x;
	}
	splay(rt,x);
}
void del(int v)
{
	find(rt,v);
	if(!rt || v!=val[rt]) return;
	cnt[rt]--;siz[rt]--;
	if(!cnt[rt])
	{
		int x=son[rt][0];
		int y=son[rt][1];
		fa[x]=fa[y]=0;
		rt=merge(x,y);
	}
}
int get_rank(int v)
{
	find(rt,v);
	return siz[son[rt][0]]+(val[rt]<v?cnt[rt]:0)+1;
}
int get_prev(int v)
{
	find(rt,v);
	if(rt && val[rt]<v) return val[rt];
	loc(son[rt][0],siz[son[rt][0]]);
	return val[son[rt][0]];
}
int get_next(int v)
{
	find(rt,v);
	if(rt && val[rt]>v) return val[rt];
	loc(son[rt][1],1);
	return val[son[rt][1]];
}
signed main()
{
//	freopen("P3369_4.in","r",stdin);
//	freopen("chj.out","w",stdout);
	int q;fin>>q;
	while(q--)
	{
		int op,x;
		fin>>op>>x;
		if(op==1) ins(x);
		else if(op==2)del(x);
		else if(op==3) fout<<get_rank(x)<<"\n";
		else if(op==4) fout<<get_num(x)<<"\n";
		else if(op==5) fout<<get_prev(x)<<"\n";
		else fout<<get_next(x)<<"\n";
	}
	return 0;
}

区间splay(是指针)

int n,m;
struct TreeNode
{
	int lazy,siz,val;
	TreeNode* son[2];
	TreeNode* fa;
};
TreeNode* rt=nullptr;
int dir(TreeNode* x)
{
	if(x->fa==nullptr) return 0;
	return x==x->fa->son[1];
}
void push_up(TreeNode* x)
{
	x->siz=1+((x->son[0]==nullptr)?0:x->son[0]->siz)+((x->son[1]==nullptr)?0:x->son[1]->siz);
}
void rotate(TreeNode* x)
{
	TreeNode* y=x->fa;
	TreeNode* z=(y==nullptr)?nullptr:y->fa;
	int r=dir(x);
	y->son[r]=x->son[!r];
	x->son[!r]=y;
	if(z!=nullptr) z->son[dir(y)]=x;
	if(y->son[r]!=nullptr) y->son[r]->fa=y;
	x->fa=z;
	y->fa=x;
	push_up(y);
	push_up(x);
}
void splay(TreeNode*& z,TreeNode* x)
{
	TreeNode* w=(z==nullptr)?nullptr:z->fa;
	for(TreeNode* y;(y=x->fa)!=w;rotate(x))
	{
		if(y->fa!=w) rotate((dir(x)==dir(y))?y:x);
	}
	z=x;
}
void build()
{
	TreeNode* y;
	for(int i=1;i<=n+2;i++)
	{
		TreeNode* x=new TreeNode;
		if(i==1) y=x;
		x->son[0]=rt;
		x->son[1]=nullptr;
		x->val=i-1;
		x->lazy=0;
		if(rt!=nullptr) rt->fa=x;
		rt=x;
		push_up(x);
	}
	splay(rt,y);
}
void lazy_reverse(TreeNode* x)
{
	swap(x->son[0],x->son[1]);
	x->lazy^=1;
}
void push_down(TreeNode* x)
{
	if(x->lazy==1)
	{
		if(x->son[0]!=nullptr) lazy_reverse(x->son[0]);
		if(x->son[1]!=nullptr) lazy_reverse(x->son[1]);
		x->lazy=0;
	}
}
void loc(TreeNode*& z,int rk)
{
	TreeNode* x=z;
	while(1)
	{
		push_down(x);
		if(rk<=((x->son[0]==nullptr)?0:x->son[0]->siz))
		{
			x=x->son[0];
		}
		else if(rk==((x->son[0]==nullptr)?0:x->son[0]->siz)+1) break;
		else
		{
			rk-=((x->son[0]==nullptr)?0:x->son[0]->siz)+1;
			x=x->son[1];
		}
	}
	splay(z,x);
}
void reverse(int l,int r)
{
	loc(rt,l);
	loc(rt->son[1],r-l+2);
	TreeNode* x=(rt->son[1]==nullptr)?nullptr:rt->son[1]->son[0];
	lazy_reverse(x);
	push_down(x);
	splay(rt,x);
}
void prin(TreeNode* x)
{
	if(x==nullptr) return;
	push_down(x);
	prin(x->son[0]);
	cout<<x->val<<" ";
	prin(x->son[1]);
}
void print()
{
	loc(rt,1);
	loc(rt->son[1],n+1);
	prin(rt->son[1]->son[0]);
}
int main()
{
	cin>>n>>m;
	build();
	while(m--)
	{
		int l,r;
		cin>>l>>r;
		reverse(l,r);
	}
	print();
	return 0;
}

替罪羊树

const int N=100010;
const double Alpha=0.7;
int tot_active,id,rt,n_tmp,a[N];
struct node
{
	int tot,cnt,siz,val,lid,rid;
} t[N];
il void push_up(int x)
{
	t[x].siz=t[t[x].lid].siz+t[t[x].rid].siz+t[x].cnt;
	t[x].tot=t[t[x].lid].tot+t[t[x].rid].tot+1;
}
il void flatten(int x)
{
	if(!x) return;
	flatten(t[x].lid);
	if(t[x].cnt) a[++n_tmp]=x;
	flatten(t[x].rid);
}
il int build(int l,int r)
{
	if(l>r) return 0;
	int mid=(l+r)>>1;
	int x=a[mid];
	t[x].lid=build(l,mid-1);
	t[x].rid=build(mid+1,r);
	push_up(x);
	return x;
}
il void rebuild(int& x)
{
	n_tmp=0;
	flatten(x);
	x=build(1,n_tmp);
}
il bool ins(int& x,int v,int dep)
{
	bool check=false;
	if(!x)
	{
		x=++id;
		t[x].val=v;
		check=dep>log(t[rt].tot+1)/log(1/Alpha);
	}
	if(t[x].val==v)
	{
		if(!t[x].cnt) tot_active++;
		t[x].cnt++;
	}
	else if(v<t[x].val) check=ins(t[x].lid,v,dep+1);
	else check=ins(t[x].rid,v,dep+1);
	push_up(x);
	if(check && max(t[t[x].lid].tot,t[t[x].rid].tot)>Alpha*t[x].tot)
	{
		rebuild(x);
		return false;
	}
	return check;
}
il bool del(int x,int v)
{
	if(!x) return false;
	int flag=1;
	if(v<t[x].val) flag=del(t[x].lid,v);
	else if(v>t[x].val) flag=del(t[x].rid,v);
	else if(t[x].cnt)
	{
		t[x].cnt--;
		if(!t[x].cnt) tot_active--;
	}
	else flag=0;
	push_up(x);
	return flag;
}
il int query_rk(int x,int v)
{
//	fout<<t[x].val<<"!@#\n";
	if(!x) return 0;
	if(v<=t[x].val) return query_rk(t[x].lid,v);
	else if(v>t[x].val) return t[t[x].lid].siz+t[x].cnt+query_rk(t[x].rid,v);
}
il int query_kth(int x,int v)
{
//	cout<<t[x].siz<<" "<<v<<"\n";
	if(v<=t[t[x].lid].siz) return query_kth(t[x].lid,v);
	else if(v>t[t[x].lid].siz+t[x].cnt) return query_kth(t[x].rid,v-(t[t[x].lid].siz+t[x].cnt));
	else return t[x].val;
}
il void ins_node(int x)
{
	ins(rt,x,0);
}
il void del_node(int x)
{
	bool flag=del(rt,x);
	if(!tot_active) rt=0;
	else if(flag && tot_active<t[rt].tot*Alpha) rebuild(rt);
}
il int get_rk(int x)
{
	return query_rk(rt,x)+1;
}
il int get_kth(int x)
{
	return query_kth(rt,x);
}
signed main()
{
//	freopen("input4.in","r",stdin);
//	freopen(".out","w",stdout);
	int q;fin>>q;
	while(q--)
	{
		int op,x;fin>>op>>x;
//		cout<<op<<" "<<x<<"\n";
		if(op==1) ins_node(x);
		if(op==2) del_node(x);
		if(op==3) fout<<get_rk(x)<<"\n";
		if(op==4) fout<<get_kth(x)<<"\n";
		if(op==5) fout<<get_kth(get_rk(x)-1)<<"\n";
		if(op==6) fout<<get_kth(get_rk(x+1))<<"\n";
//		fout<<t[rt].tot<<" "<<t[rt].siz<<"\n";
	}
	return 0;
}

无旋treap

struct TreeNode
{
	int val,siz,rank,cnt;
	TreeNode* son[2];
};
TreeNode* rt=nullptr;
void push_up(TreeNode* x)
{
	x->siz=((x->son[0]==nullptr)?0:x->son[0]->siz)+((x->son[1]==nullptr)?0:x->son[1]->siz)+x->cnt;
}
pair<TreeNode*,TreeNode*> split(TreeNode* x,int w)
{
	if(x==nullptr) return {nullptr,nullptr};
	if(x->val<=w)
	{
		auto temp=split(x->son[1],w);
		x->son[1]=temp.first;
		push_up(x);
		return {x,temp.second};
	}
	else
	{
		auto temp=split(x->son[0],w);
		x->son[0]=temp.second;
		push_up(x);
		return {temp.first,x};
	}
}
pair<TreeNode*,pair<TreeNode*,TreeNode*>> split_by_rk(TreeNode* x,int rk)
{
	if(x==nullptr) return {nullptr,{nullptr,nullptr}};
	int lid_siz=(x->son[0]==nullptr)?0:x->son[0]->siz;
	if(rk<=lid_siz)
	{
		auto temp=split_by_rk(x->son[0],rk);
		x->son[0]=temp.second.second;
		push_up(x);
		return {temp.first,{temp.second.first,x}};
	}
	else if(rk<=lid_siz+x->cnt)
	{
		TreeNode* l;
		TreeNode* r;
		l=x->son[0];
		r=x->son[1];
		x->son[0]=x->son[1]=nullptr;
		push_up(x);
		return {l,{x,r}};
	}
	else
	{
		auto temp=split_by_rk(x->son[1],rk-lid_siz-x->cnt);
		x->son[1]=temp.first;
		push_up(x);
		return {x,{temp.second.first,temp.second.second}};
	}
}
TreeNode* merge(TreeNode* x,TreeNode* y)
{
	if(x==nullptr) return y;
	if(y==nullptr) return x;
	if(x->rank<y->rank)
	{
		x->son[1]=merge(x->son[1],y);
		push_up(x);
		return x;
	}
	else
	{
		y->son[0]=merge(x,y->son[0]);
		push_up(y);
		return y;
	}
}
void ins(int w)
{
	auto temp1=split(rt,w);
	auto temp2=split(temp1.first,w-1);
	TreeNode* x;
	if(temp2.second==nullptr)
	{
		x=new TreeNode;
		x->son[0]=x->son[1]=nullptr;
		x->siz=x->cnt=1;
		x->val=w;
		x->rank=rand();
	}
	else
	{
		temp2.second->cnt++;
		push_up(temp2.second);
	}
	TreeNode* temp=merge(temp2.first,(temp2.second==nullptr)?x:temp2.second);
	rt=merge(temp,temp1.second);
}
void del(int w)
{
	auto temp1=split(rt,w);
	auto temp2=split(temp1.first,w-1);
	if(temp2.second->cnt>1)
	{
		temp2.second->cnt--;
		push_up(temp2.second);
		temp2.first=merge(temp2.first,temp2.second);
	}
	else
	{
		if(temp1.first==temp2.second)
		{
			temp1.first==nullptr;
		}
		delete temp2.second;
		temp2.second=nullptr;
	}
	rt=merge(temp2.first,temp1.second);
}
int get_rank(TreeNode* x,int w)
{
	auto temp=split(x,w-1);
	int ret=((temp.first==nullptr)?0:temp.first->siz)+1;
	x=merge(temp.first,temp.second);
	return ret;
}
int get_num(TreeNode* x,int w)
{
	auto temp=split_by_rk(x,w);
	int ret=temp.second.first->val;
	x=merge(temp.first,merge(temp.second.first,temp.second.second));
	return ret;
}
int get_prev(int w)
{
	auto temp=split(rt,w-1);
	int ret=get_num(temp.first,temp.first->siz);
	rt=merge(temp.first,temp.second);
	return ret;
}
int get_next(int w)
{
	auto temp=split(rt,w);
	int ret=get_num(temp.second,1);;
	rt=merge(temp.first,temp.second);
	return ret;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	srand(time(NULL));
	int m;
	cin>>m;
	while(m--)
	{
		int op;
		cin>>op;
		if(op==1)
		{
			int x;
			cin>>x;
			ins(x);
		}
		else if(op==2)
		{
			int x;
			cin>>x;
			del(x);
		}
		else if(op==3)
		{
			int x;
			cin>>x;
			cout<<get_rank(rt,x)<<"\n";
		}
		else if(op==4)
		{
			int x;
			cin>>x;
			cout<<get_num(rt,x)<<"\n";
		}
		else if(op==5)
		{
			int x;
			cin>>x;
			cout<<get_prev(x)<<"\n";
		}
		else
		{
			int x;
			cin>>x;
			cout<<get_next(x)<<"\n";
		}
	}
	return 0;
}

cdq分治

const int N=100010;
int n,m,k,ans[N],f[N],val[N],sum[N<<1];
struct node
{
	int idx,a,b,c,val;
} a[N],tmp[N];
bool operator <(node x,node y)
{
	if(x.a!=y.a) return x.a<y.a;
	else if(x.b!=y.b) return x.b<y.b;
	return x.c<y.c;
}
map<node,int> mp;
void add(int x,int w)
{
	for(int i=x;i<=k;i+=i&-i) sum[i]+=w;
}
int query(int x)
{
	int ret=0;
	for(int i=x;i;i-=i&-i) ret+=sum[i];
	return ret;
}
void cdq(int l,int r)
{
	if(l==r) return;
	int mid=(l+r)>>1;
	cdq(l,mid);cdq(mid+1,r);
	int i=l,j=mid+1,idx=l;
	while(i<=mid && j<=r)
	{
		if(a[i].b<=a[j].b)
		{
			add(a[i].c,a[i].val);
			tmp[idx++]=a[i++];
		}
		else
		{
			ans[a[j].idx]+=query(a[j].c);
			tmp[idx++]=a[j++];
		}
	}
	while(i<=mid) add(a[i].c,a[i].val),tmp[idx++]=a[i++];
	while(j<=r)
	{
		ans[a[j].idx]+=query(a[j].c);
		tmp[idx++]=a[j++];
	}
	for(int f=l;f<=mid;f++) add(a[f].c,-a[f].val);
	for(int i=l;i<=r;i++) a[i]=tmp[i];
}
signed main()
{
	fin>>n>>k;
	for(int i=1;i<=n;i++)
	{
		int A,B,C;fin>>A>>B>>C;
		mp[{0,A,B,C,0}]++;
	}
	for(auto i:mp)
	{
		m++;
		a[m]={m,i.first.a,i.first.b,i.first.c,i.second};
		val[m]=i.second;
	}
	cdq(1,m);
	for(int i=1;i<=m;i++) f[ans[i]+val[i]-1]+=val[i];
	for(int i=0;i<n;i++) fout<<f[i]<<"\n";
	return 0;
}

李超线段树

const int N=100010,inf=1e9;
const double eps=1e-10;
int idx[N<<2],tot;
struct node
{
	double k,b;
	double operator [](int x){return k*x+b;}
} f[N];
void upd(int id,int l,int r,int k)
{
	if(!idx[id])
	{
		idx[id]=k;
		return;
	}
	int mid=(l+r)>>1;
	if(f[k][mid]-f[idx[id]][mid]>eps || (fabs(f[k][mid]-f[idx[id]][mid])<eps && k<idx[id])) swap(idx[id],k);
	if(f[k][l]-f[idx[id]][l]>eps || (fabs(f[k][l]-f[idx[id]][l])<eps && k<idx[id])) upd(lid,l,mid,k);
	if(f[k][r]-f[idx[id]][r]>eps || (fabs(f[k][r]-f[idx[id]][r])<eps && k<idx[id])) upd(rid,mid+1,r,k);
}
void add(int id,int l,int r,int L,int R,int k)
{
	if(L<=l && r<=R)
	{
		upd(id,l,r,k);
		return;
	}
	int mid=(l+r)>>1;
	if(L<=mid) add(lid,l,mid,L,R,k);
	if(R>mid) add(rid,mid+1,r,L,R,k);
}
int query(int id,int l,int r,int x)
{
	if(l==r) return idx[id];
	int mid=(l+r)>>1,ret=idx[id];
	if(x<=mid)
	{
		int tmp=query(lid,l,mid,x);
		if(f[tmp][x]-f[ret][x]>eps || (fabs(f[tmp][x]-f[ret][x])<eps && tmp<ret)) return tmp;
		else return ret;
	}
	else
	{
		int tmp=query(rid,mid+1,r,x);
		if(f[tmp][x]-f[ret][x]>eps || (fabs(f[tmp][x]-f[ret][x])<eps && tmp<ret)) return tmp;
		else return ret;
	}
}
signed main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	int q,lstans=0;fin>>q;
	f[0].b=-inf;
	while(q--)
	{
		int op;fin>>op;
		if(op==1)
		{
			tot++;
			int x,y,xx,yy;fin>>x>>y>>xx>>yy;
			x=(x+lstans-1)%39989+1;xx=(xx+lstans-1)%39989+1;
			y=(y+lstans-1)%1000000000+1;yy=(yy+lstans-1)%1000000000+1;
			if(x>xx) swap(x,xx),swap(y,yy);
			if(x==xx)
			{
				f[tot].k=0;f[tot].b=max(y,yy);
			}
			else
			{
				f[tot].k=1.0*(y-yy)/(x-xx);
				f[tot].b=y-f[tot].k*x;
			}
			add(1,1,39989,x,xx,tot);
		}
		else
		{
			int x;fin>>x;x=(x+lstans-1)%39989+1;
			fout<<(lstans=query(1,1,39989,x))<<"\n";
		}
	}
	return 0;
}

线段树分裂

const int N=200010;
int idx[N],d[N],tot,son[N][26],fail[N],ans[N];
queue<int> q;
void get_fail()
{
	for(int i=0;i<26;i++) if(son[0][i]) q.push(son[0][i]);
	while(!q.empty())
	{
		int u=q.front();q.pop();
		for(int i=0;i<26;i++)
		{
			if(son[u][i])
			{
				fail[son[u][i]]=son[fail[u]][i];
				d[fail[son[u][i]]]++;
				q.push(son[u][i]);
			}
			else son[u][i]=son[fail[u]][i];
		}
	}
}
signed main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	int n;cin>>n;
	for(int i=1;i<=n;i++)
	{
		string t;cin>>t;
		int now=0;
		for(int j=0;j<(int)t.size();j++)
		{
			int c=t[j]-'a';
			if(!son[now][c]) son[now][c]=++tot;
			now=son[now][c];
		}
		idx[i]=now;
	}
	get_fail();
	string s;cin>>s;
	int now=0;
	for(int i=0;i<(int)s.size();i++)
	{
		now=son[now][s[i]-'a'];
		ans[now]++;
	}
	for(int i=0;i<=tot;i++) if(!d[i]) q.push(i);
	while(!q.empty())
	{
		int u=q.front();q.pop();
		int v=fail[u];ans[v]+=ans[u];
		d[v]--;
		if(!d[v]) q.push(v);
	}
	for(int i=1;i<=n;i++) cout<<ans[idx[i]]<<"\n";
	return 0;
}

吉司机线段树

#define lid id<<1
#define rid id<<1|1
const int N=500010,inf=1e18;
int a[N];
struct TreeNode
{
	int mxh,mx,cmx,sum,lazymx,lazycmx,lazymxh,lazycmxh,cntmx;
} t[N<<2];
void push_up(int id)
{
	t[id].sum=t[lid].sum+t[rid].sum;
	t[id].mx=max(t[lid].mx,t[rid].mx);
	t[id].mxh=max(t[lid].mxh,t[rid].mxh);
	if(t[lid].mx>t[rid].mx)
	{
		t[id].cntmx=t[lid].cntmx;
		t[id].cmx=max(t[lid].cmx,t[rid].mx);
	}
	else if(t[lid].mx<t[rid].mx)
	{
		t[id].cntmx=t[rid].cntmx;
		t[id].cmx=max(t[rid].cmx,t[lid].mx);
	}
	else
	{
		t[id].cntmx=t[lid].cntmx+t[rid].cntmx;
		t[id].cmx=max(t[lid].cmx,t[rid].cmx);
	}
}
void upd(int id,int l,int r,int valmx,int valcmx,int valmxh,int valcmxh)
{
	t[id].sum+=valmx*t[id].cntmx+valcmx*(r-l+1-t[id].cntmx);
	t[id].mxh=max(t[id].mxh,t[id].mx+valmxh);
	t[id].mx+=valmx;
	if(t[id].cmx!=-inf) t[id].cmx+=valcmx;
	t[id].lazymxh=max(t[id].lazymxh,t[id].lazymx+valmxh);
	t[id].lazymx+=valmx;
	t[id].lazycmxh=max(t[id].lazycmxh,t[id].lazycmx+valcmxh);
	t[id].lazycmx+=valcmx;
}
void push_down(int id,int l,int r)
{
	int mx=max(t[lid].mx,t[rid].mx),mid=(l+r)>>1;
	if(t[lid].mx==mx) upd(lid,l,mid,t[id].lazymx,t[id].lazycmx,t[id].lazymxh,t[id].lazycmxh);
	else upd(lid,l,mid,t[id].lazycmx,t[id].lazycmx,t[id].lazycmxh,t[id].lazycmxh);
	if(t[rid].mx==mx) upd(rid,mid+1,r,t[id].lazymx,t[id].lazycmx,t[id].lazymxh,t[id].lazycmxh);
	else upd(rid,mid+1,r,t[id].lazycmx,t[id].lazycmx,t[id].lazycmxh,t[id].lazycmxh);
	t[id].lazymx=t[id].lazymxh=t[id].lazycmx=t[id].lazycmxh=0;
}
void build(int id,int l,int r)
{
	if(l==r)
	{
		t[id].sum=t[id].mx=t[id].mxh=a[l];
		t[id].cmx=-inf;t[id].cntmx=1;
		return;
	}
	int mid=(l+r)>>1;
	build(lid,l,mid);build(rid,mid+1,r);
	push_up(id);
}
void add(int id,int l,int r,int L,int R,int k)
{
	if(L<=l&& r<=R)
	{
		upd(id,l,r,k,k,k,k);
		return;
	}
	push_down(id,l,r);
	int mid=(l+r)>>1;
	if(L<=mid) add(lid,l,mid,L,R,k);
	if(R>mid) add(rid,mid+1,r,L,R,k);
	push_up(id);
}
void upd_min(int id,int l,int r,int L,int R,int k)
{
	if(t[id].mx<=k) return;
	if(L<=l && r<=R && t[id].cmx<k)
	{
		upd(id,l,r,k-t[id].mx,0,k-t[id].mx,0);
		return;
	}
	push_down(id,l,r);
	int mid=(l+r)>>1;
	if(L<=mid) upd_min(lid,l,mid,L,R,k);
	if(R>mid) upd_min(rid,mid+1,r,L,R,k);
	push_up(id);
}
int query_sum(int id,int l,int r,int L,int R)
{
	if(L<=l && r<=R) return t[id].sum;
	push_down(id,l,r);
	int mid=(l+r)>>1,ret=0;
	if(L<=mid) ret+=query_sum(lid,l,mid,L,R);
	if(R>mid) ret+=query_sum(rid,mid+1,r,L,R);
	return ret;
}
int query_mx(int id,int l,int r,int L,int R)
{
	if(L<=l && r<=R) return t[id].mx;
	push_down(id,l,r);
	int mid=(l+r)>>1,ret=-inf;
	if(L<=mid) ret=max(ret,query_mx(lid,l,mid,L,R));
	if(R>mid) ret=max(ret,query_mx(rid,mid+1,r,L,R));
	return ret;
}
int query_mxh(int id,int l,int r,int L,int R)
{
	if(L<=l && r<=R) return t[id].mxh;
	push_down(id,l,r);
	int mid=(l+r)>>1,ret=-inf;
	if(L<=mid) ret=max(ret,query_mxh(lid,l,mid,L,R));
	if(R>mid) ret=max(ret,query_mxh(rid,mid+1,r,L,R));
	return ret;
}
signed main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	int n,q;fin>>n>>q;
	for(int i=1;i<=n;i++) fin>>a[i];
	build(1,1,n);
	while(q--)
	{
		int op,l,r;fin>>op>>l>>r;
		if(op==1)
		{
			int k;fin>>k;
			add(1,1,n,l,r,k);
		}
		else if(op==2)
		{
			int k;fin>>k;
			upd_min(1,1,n,l,r,k);
		}
		else if(op==3) fout<<query_sum(1,1,n,l,r)<<"\n";
		else if(op==4) fout<<query_mx(1,1,n,l,r)<<"\n";
		else fout<<query_mxh(1,1,n,l,r)<<"\n";
	}
	return 0;
}

图论

虚树

il bool cmp(int x,int y){return dfn[x]<dfn[y];}
il void build()
{
	sort(a+1,a+1+m,cmp);
	st[tp=1]=1;
	for(int i=1;i<=m;i++)
	{
		if(a[i]==st[tp]) continue;
		int lca=get_lca(a[i],st[tp]);
		if(lca!=st[tp])
		{
			while(dfn[lca]<dfn[st[tp-1]])
			{
				e[st[tp-1]].push_back(st[tp]);
				tp--;
			}
			if(lca==st[tp-1])
			{
				e[st[tp-1]].push_back(st[tp]);
				tp--;
			}
			else
			{
				e[lca].push_back(st[tp]);
				st[tp]=lca;
			}
		}
		st[++tp]=a[i];
	}
	for(int i=1;i<tp;i++) e[st[i]].push_back(st[i+1]);
}

dinic最大流

const int N=210,M=5010,inf=1e18;
int n,m,S,T,ans,h[N],tot=1,cur[N],d[N];
queue<int> q;
struct edge
{
	int to,nxt,w;
} e[M<<1];
il void add(int u,int v,int w)
{
	tot++;
	e[tot].to=v;e[tot].w=w;
	e[tot].nxt=h[u];
	h[u]=tot;
}
il bool bfs()
{
	for(int i=1;i<=n;i++) cur[i]=h[i];
	for(int i=1;i<=n;i++) d[i]=0;
	d[S]=1;q.push(S);
	while(!q.empty())
	{
		int u=q.front();q.pop();
		for(int i=h[u];i;i=e[i].nxt)
		{
			int v=e[i].to;
			if(e[i].w && !d[v])
			{
				d[v]=d[u]+1;
				q.push(v);
			}
		}
//		cout<<u<<"\n";
	}
	return d[T]>0;
}
int dfs(int u,int val)
{
	if(u==T) return val;
	int w=0;
	for(int& i=cur[u];i;i=e[i].nxt)
	{
		int v=e[i].to;
		if(e[i].w>0 && d[v]==d[u]+1)
		{
			int x=dfs(v,min(val-w,e[i].w));
			if(x>0) w+=x,e[i].w-=x,e[i^1].w+=x;
			if(w==val) return w;
		}
//		cout<<"\n";
	}
	return w;
}
il void Dinic()
{
	ans=0;
	while(bfs()) ans+=dfs(S,inf);
}
signed main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	fin>>n>>m>>S>>T;
	for(int i=1;i<=m;i++)
	{
		int u,v,w;fin>>u>>v>>w;
		add(u,v,w);add(v,u,0);
	}
	Dinic();
	fout<<ans;
	return 0;
}

zkw最小费用最大流

const int N=5010,M=50010,inf=1e9;
int h[N],tot=1,cur[N],ansf,ansc,n,m,S,T,vis[N];
int dis[N];
queue<int> q;
struct edge
{
	int to,nxt,w,cost;
} e[M<<1];
il void add(int u,int v,int w,int cost)
{
	tot++;
	e[tot].nxt=h[u];e[tot].w=w;
	e[tot].cost=cost;e[tot].to=v;
	h[u]=tot;
}
il bool bfs()
{
	for(int i=1;i<=n;i++) cur[i]=h[i];
	for(int i=1;i<=n;i++) dis[i]=inf;
	dis[S]=0;q.push(S);vis[S]=1;
	while(!q.empty())
	{
		int u=q.front();q.pop();vis[u]=0;
//		fout<<u<<" "<<dis[u]<<"\n";
		for(int i=h[u];i;i=e[i].nxt)
		{
			int v=e[i].to;
			if(e[i].w && dis[v]>dis[u]+e[i].cost)
			{
				dis[v]=dis[u]+e[i].cost;
				if(!vis[v]) vis[v]=1,q.push(v);
			}
		}
	}
	return dis[T]!=inf;
}
int dfs(int u,int val)
{
	if(u==T) return val;
	int w=0;vis[u]=1;
	for(int& i=cur[u];i;i=e[i].nxt)
	{
		int v=e[i].to;
		if(e[i].w && dis[v]==dis[u]+e[i].cost && !vis[v])
		{
			int x=dfs(v,min(e[i].w,val-w));
			if(x>0) ansc+=x*e[i].cost,w+=x,e[i].w-=x,e[i^1].w+=x;
			if(w==val)
			{
				vis[u]=0;
				return w;
			}
		}
	}
	vis[u]=0;
	return w;
}
il void zkw()
{
	while(bfs()) ansf+=dfs(S,inf);
}
signed main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	fin>>n>>m>>S>>T;
	for(int i=1;i<=m;i++)
	{
		int u,v,w,cost;fin>>u>>v>>w>>cost;
		add(u,v,w,cost);add(v,u,0,-cost);
	}
	zkw();
	fout<<ansf<<" "<<ansc<<"\n";
	return 0;
}

有源汇上下界最大流

const int N=1010,M=10010,inf=1e18;
int n,m,h[N],cur[N],tot=1,ansf,dis[N],d[N],SS,TT,S,T;
struct edge
{
	int to,nxt,w;
} e[M<<2];
queue<int> q;
il void add(int u,int v,int w)
{
	tot++;
	e[tot].to=v;e[tot].w=w;
	e[tot].nxt=h[u];h[u]=tot;
}
il void add_edge(int u,int v,int w)
{
	add(u,v,w);add(v,u,0);
}
il bool bfs()
{
	for(int i=1;i<=n;i++) cur[i]=h[i],dis[i]=0;
	dis[SS]=1;q.push(SS);
	while(!q.empty())
	{
		int u=q.front();q.pop();
		for(int i=h[u];i;i=e[i].nxt)
		{
			int v=e[i].to;
			if(e[i].w && !dis[v])
			{
				dis[v]=dis[u]+1;
				q.push(v);
			}
		}
	}
	return dis[TT]>0;
}
int dfs(int u,int val)
{
	if(u==TT) return val;
	int w=0;
	for(int& i=cur[u];i;i=e[i].nxt)
	{
		int v=e[i].to;
		if(e[i].w && dis[v]==dis[u]+1)
		{
			int x=dfs(v,min(e[i].w,val-w));
			if(x) w+=x,e[i].w-=x,e[i^1].w+=x;
			if(val==w) return w;
		}
	}
	return w;
}
il void Dinic()
{
	while(bfs()) ansf+=dfs(SS,inf);
}
signed main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	fin>>n>>m>>S>>T;
	n+=2;SS=n-1,TT=n;
	for(int i=1;i<=m;i++)
	{
		int u,v,l,r;fin>>u>>v>>l>>r;
		d[v]+=l,d[u]-=l;
		add_edge(u,v,r-l);
	}
	for(int i=1;i<=n;i++)
	{
		if(d[i]>0) add_edge(SS,i,d[i]);
		else if(d[i]<0) add_edge(i,TT,-d[i]);
	}
	add_edge(T,S,inf);
	Dinic();
	for(int i=h[SS];i;i=e[i].nxt)
	{
		if(e[i].w!=0)
		{
			fout<<"N";
			return 0;
		}
	}
	ansf=e[tot].w;
	SS=S,TT=T;
	e[tot].w=e[tot-1].w=0;
	Dinic();
	fout<<ansf<<"\n";
	return 0;
}

有源汇上下界最小流

const int N=1010,M=10010,inf=1e18;
int n,m,S,T,SS,TT,h[N],cur[N],tot=1,d[N],dis[N],ansf;
queue<int> q;
struct edge
{
	int v,next,w;
} e[(N+M)<<1];
void add(int u,int v,int w)
{
	e[++tot].next=h[u];
	e[tot].v=v;e[tot].w=w;
	h[u]=tot;
}
void add_edge(int u,int v,int w)
{
	add(u,v,w);add(v,u,0);
}
bool bfs()
{
	for(int i=1;i<=n;i++) cur[i]=h[i],dis[i]=0;
	dis[SS]=1;q.push(SS);
	while(!q.empty())
	{
		int u=q.front();
		q.pop();
		for(int i=h[u];i;i=e[i].next)
		{
			int v=e[i].v;
			if(e[i].w && !dis[v])
			{
				dis[v]=dis[u]+1;
				q.push(v);
			}
		}
	}
	return dis[TT]>0;
}
int dfs(int u,int val)
{
	if(u==TT) return val;
	int w=0;
	for(int& i=cur[u];i;i=e[i].next)
	{
		int v=e[i].v;
		if(dis[v]==dis[u]+1 && e[i].w)
		{
			int x=dfs(v,min(e[i].w,val-w));
			if(x>0) w+=x,e[i].w-=x,e[i^1].w+=x;
			if(w==val) return w;
		}
	}
	return w;
}
void dinic()
{
	while(bfs())
	{
		ansf+=dfs(SS,inf);
//		cout<<ansf<<"\n";
	}
}
signed main()
{
	fin>>n>>m>>S>>T;
	n+=2;SS=n-1,TT=n;
	for(int i=1;i<=m;i++)
	{
		int u,v,l,r;fin>>u>>v>>l>>r;
		ansf+=l;
		d[v]+=l;d[u]-=l;
		add_edge(u,v,r-l);
	}
	for(int i=1;i<=n;i++)
	{
		if(d[i]>0) add_edge(SS,i,d[i]);
		else if(d[i]<0) add_edge(i,TT,-d[i]);
	}
	add_edge(T,S,inf);
	dinic();
	for(int i=h[SS];i;i=e[i].next)
	{
		if(e[i].w!=0)
		{
			fout<<"N";
			return 0;
		}
	}
	int w=e[tot].w;
	ansf=0;
	SS=T,TT=S;
	e[tot].w=e[tot-1].w=0;
	dinic();
	fout<<w-ansf;
	return 0;
}

无源汇上下界可行流

const int N=1010,M=10010,inf=1e18;
int n,m,S,T,SS,TT,h[N],cur[N],ans[M],tot=1,d[N],dis[N],ansf;
queue<int> q;
struct edge
{
	int v,next,w,idx;
} e[(N+M)<<1];
void add(int u,int v,int w,int idx)
{
	e[++tot].next=h[u];
	e[tot].idx=idx;
	e[tot].v=v;e[tot].w=w;
	h[u]=tot;
}
void add_edge(int u,int v,int w,int idx)
{
	add(u,v,w,idx);add(v,u,0,idx);
}
bool bfs()
{
	for(int i=1;i<=n;i++) cur[i]=h[i],dis[i]=0;
	dis[SS]=1;q.push(SS);
	while(!q.empty())
	{
		int u=q.front();
		q.pop();
		for(int i=h[u];i;i=e[i].next)
		{
			int v=e[i].v;
			if(e[i].w && !dis[v])
			{
				dis[v]=dis[u]+1;
				q.push(v);
			}
		}
	}
	return dis[TT]>0;
}
int dfs(int u,int val)
{
	if(u==TT) return val;
	int w=0;
	for(int& i=cur[u];i;i=e[i].next)
	{
		int v=e[i].v;
		if(dis[v]==dis[u]+1 && e[i].w)
		{
			int x=dfs(v,min(e[i].w,val-w));
			if(x>0) w+=x,e[i].w-=x,e[i^1].w+=x;
			if(w==val) return w;
		}
	}
	return w;
}
void dinic()
{
	while(bfs())
	{
		ansf+=dfs(SS,inf);
//		cout<<ansf<<"\n";
	}
}
signed main()
{
	fin>>n>>m;
	n+=2;SS=n-1,TT=n;
	for(int i=1;i<=m;i++)
	{
		int u,v,l,r;fin>>u>>v>>l>>r;
		ans[i]=l;
		d[v]+=l;d[u]-=l;
		add_edge(u,v,r-l,i);
	}
	for(int i=1;i<=n;i++)
	{
		if(d[i]>0) add_edge(SS,i,d[i],m+1);
		else if(d[i]<0) add_edge(i,TT,-d[i],m+1);
	}
	dinic();
	for(int i=h[SS];i;i=e[i].next)
	{
		if(e[i].w!=0)
		{
			fout<<"No";
			return 0;
		}
	}
	for(int i=3;i<=tot;i+=2)
	{
		ans[e[i].idx]+=e[i].w;
	}
	fout<<"Yes\n";
	for(int i=1;i<=m;i++) fout<<ans[i]<<"\n";
	return 0;
}

LCT

#define il inline
const int N=100010,V=12;
struct node
{
	int val,sum,fa,son[2],tag;
} t[N];
il bool Get(int x){return t[t[x].fa].son[1]==x;}
il bool is_root(int x){return t[t[x].fa].son[0]!=x && t[t[x].fa].son[1]!=x;}
il void push_up(int x)
{
	t[x].sum=t[t[x].son[0]].sum^t[t[x].son[1]].sum^t[x].val;
}
il void lazy_reverse(int x)
{
	swap(t[x].son[0],t[x].son[1]);
	t[x].tag^=1;
}
il void push_down(int x)
{
	if(t[x].tag)
	{
		lazy_reverse(t[x].son[0]);
		lazy_reverse(t[x].son[1]);
		t[x].tag=0;
	}
}
il void update(int x)
{
	if(!is_root(x)) update(t[x].fa);
	push_down(x);
}
il void rotate(int x)
{
	int y=t[x].fa,z=t[y].fa,r=Get(x);
	if(!is_root(y)) t[z].son[t[z].son[1]==y]=x;
	t[y].son[r]=t[x].son[!r],t[t[x].son[!r]].fa=y;
	t[x].son[!r]=y,t[y].fa=x,t[x].fa=z;
	push_up(y),push_up(x);
}
il void splay(int x)
{
	update(x);
	for(int fa;fa=t[x].fa,!is_root(x);rotate(x))
	{
		if(!is_root(fa)) rotate(Get(x)==Get(fa)?fa:x);
	}
}
il int Access(int x)
{
	int p;
	for(p=0;x;p=x,x=t[x].fa)
	{
		splay(x),t[x].son[1]=p,push_up(x);
	}
	return p;
}
il void make_root(int x)
{
	x=Access(x);
	lazy_reverse(x);
}
il void Link(int u,int v)
{
	make_root(u);
	splay(u);
	t[u].fa=v;
}
il void Split(int u,int v)
{
	make_root(u);
	Access(v);
	splay(v);
}
il int Find(int u)
{
	Access(u);
	splay(u);
	push_down(u);
	while(t[u].son[0]) u=t[u].son[0],push_down(u);
	splay(u);
	return u;
}
il void Cut(int u,int v)
{
	if(Find(u)!=Find(v)) return;
	Split(u,v);
	if(t[u].fa!=v || t[u].son[1]) return;
	t[u].fa=t[v].son[0]=0;
}
signed main()
{
//	freopen("b1.in","r",stdin);
//	freopen("chj.out","w",stdout);
	int n,q;cin>>n>>q;
	for(int i=1;i<=n;i++) cin>>t[i].val; 
	while(q--)
	{
		int op;cin>>op;
		if(op==1)
		{
			int u,v;cin>>u>>v;
			if(Find(u)!=Find(v)) Link(u,v);
		}
		if(op==2)
		{
			int u,v;cin>>u>>v;
			Cut(u,v);
		}
		if(op==3)
		{
			int c,f;cin>>c>>f;
			splay(c);
			t[c].val=f;
			push_up(c);
		}
		if(op==0)
		{
			int u,v;cin>>u>>v;
			Split(u,v);
			cout<<t[v].sum<<"\n";
		}
	}
	return 0;
}

tarjan缩点

const int N=10010;
int dp[N],dfn[N],low[N],tot,scc[N],vis[N],st[N],tp,cnt,val[N],a[N],d[N];
queue<int> q;
vector<int> g[N],e[N];
void tarjan(int u)
{
	low[u]=dfn[u]=++tot;
	vis[u]=1;st[++tp]=u;
	for(int v:g[u])
	{
		if(!dfn[v])
		{
			tarjan(v);
			low[u]=min(low[u],low[v]);
		}
		else if(vis[v])
		{
			low[u]=min(low[u],dfn[v]);
		}
	}
	if(dfn[u]==low[u])
	{
		int v=0;cnt++;
		while(v!=u)
		{
			v=st[tp--];
			vis[v]=0;
			scc[v]=cnt;
			val[cnt]+=a[v];
		}
	}
}
signed main()
{
	int n,m;fin>>n>>m;
	for(int i=1;i<=n;i++) fin>>a[i];
	for(int i=1;i<=m;i++)
	{
		int u,v;
		fin>>u>>v;
		g[u].push_back(v);
	}
	for(int i=1;i<=n;i++)
	{
		if(!dfn[i]) tarjan(i);
	}
	for(int i=1;i<=n;i++)
	{
		for(int v:g[i])
		{
			if(scc[i]!=scc[v])
			{
				e[scc[i]].push_back(scc[v]);
				d[scc[v]]++;
			}
		}
	}
	for(int i=1;i<=cnt;i++)
	{
		if(d[i]==0)
		{
			dp[i]=val[i];
			q.push(i);
		}
	}
	while(!q.empty())
	{
		int u=q.front();
		q.pop();
		for(int v:e[u])
		{
			d[v]--;
			dp[v]=max(dp[v],dp[u]+val[v]);
			if(d[v]==0) q.push(v);
		}
	}
	int ans=0;
	for(int i=1;i<=cnt;i++) ans=max(ans,dp[i]);
	fout<<ans; 
	return 0;
}

tarjan求割点

int dfn[20010],low[20010],tot,ge[20010],cnt,ans[20010];
stack<int> st;
vector<int> g[20010];
void tarjan(int x,int fa)
{
	dfn[x]=low[x]=++tot;
	int son=0;
	for(int i=0;i<g[x].size();i++)
	{
		int y=g[x][i];
		if(!dfn[y])
		{
			son++;
			tarjan(y,x);
			low[x]=min(low[x],low[y]);
			if(dfn[x]<=low[y]) ge[x]=true;
		}
		else if(y!=fa)
		{
			low[x]=min(low[x],dfn[y]);
		}
	}
	if(fa==0 && son<2) ge[x]=false;
}
int main()
{
	int n,m;
	cin>>n>>m;
	int u,v;
	for(int i=1;i<=m;i++)
	{
		cin>>u>>v; 
		g[u].push_back(v);
		g[v].push_back(u);
	}
	for(int i=1;i<=n;i++)
	{
		if(!dfn[i])
		{
			tarjan(i,0);
		}
	}
	for(int i=1;i<=n;i++)
	{
		if(ge[i]) ans[++cnt]=i;
	}
	cout<<cnt<<"\n";
	for(int i=1;i<=cnt;i++)
	{
		cout<<ans[i]<<" ";
	}
	return 0;
}

tarjan求点双

const int N=500010,M=2000010;
int h[N],tot,cnt,ttt,dfn[N],low[N],st[N],tp,vis[N];
struct node
{
	int nxt,v;
} e[M<<1];
vector<int> b[N];
void add(int u,int v)
{
	e[tot].nxt=h[u];
	e[tot].v=v;
	h[u]=tot++;
}
void tarjan(int u,int lst)
{
	int flag=0;
	dfn[u]=low[u]=++ttt;
	st[++tp]=u;vis[u]=1;
	for(int i=h[u];i!=-1;i=e[i].nxt)
	{
		int v=e[i].v;
		if(i==(lst^1)) continue;
		if(!dfn[v])
		{
			flag=1;
			tarjan(v,i);
			low[u]=min(low[u],low[v]);
			if(low[v]>=dfn[u])
			{
				cnt++;
				while(st[tp+1]!=v)
				{
					vis[st[tp]]=0;
					b[cnt].push_back(st[tp--]);
				}
				b[cnt].push_back(u);
			}
		}
		else if(vis[v])
		{
			low[u]=min(low[u],dfn[v]);
		}
	}
	if(lst==tot && flag==0)
	{
		tp--;cnt++;
		b[cnt].push_back(u);
	}
}
signed main()
{
	int n,m;fin>>n>>m;
	for(int i=1;i<=n;i++) h[i]=-1;
	for(int i=1;i<=m;i++)
	{
		int u,v;fin>>u>>v;
		add(u,v);add(v,u);
	}
	for(int i=1;i<=n;i++)
	{
		if(!dfn[i]) tarjan(i,tot);
	}
	fout<<cnt<<"\n";
	for(int i=1;i<=cnt;i++)
	{
		fout<<b[i].size()<<" ";
		for(int j:b[i]) fout<<j<<" ";
		fout<<"\n";
	}
	return 0;
}

tarjan求边双

const int N=500010,M=2000010;
int h[N],tot,cnt,ttt,dfn[N],low[N],st[N],tp,vis[N];
struct node
{
	int nxt,v;
} e[M<<1];
vector<int> b[N];
void add(int u,int v)
{
	e[tot].nxt=h[u];
	e[tot].v=v;
	h[u]=tot++;
}
void tarjan(int u,int lst)
{
	dfn[u]=low[u]=++ttt;
	st[++tp]=u;vis[u]=1;
	for(int i=h[u];i!=-1;i=e[i].nxt)
	{
		int v=e[i].v;
		if(i==(lst^1)) continue;
		if(!dfn[v])
		{
			tarjan(v,i);
			low[u]=min(low[u],low[v]);
		}
		else if(vis[v])
		{
			low[u]=min(low[u],dfn[v]);
		}
	}
	if(dfn[u]==low[u])
	{
		int v=0;
		cnt++;
		while(v!=u)
		{
			v=st[tp--];
			vis[v]=0;
			b[cnt].push_back(v);
		}
	}
}
signed main()
{
	int n,m;fin>>n>>m;
	for(int i=1;i<=n;i++) h[i]=-1;
	for(int i=1;i<=m;i++)
	{
		int u,v;fin>>u>>v;
		add(u,v);add(v,u);
	}
	for(int i=1;i<=n;i++)
	{
		if(!dfn[i]) tarjan(i,tot);
	}
	fout<<cnt<<"\n";
	for(int i=1;i<=cnt;i++)
	{
		fout<<b[i].size()<<" ";
		for(int j:b[i]) fout<<j<<" ";
		fout<<"\n";
	}
	return 0;
}

spfa判负环

const int N=2010,inf=1e18;
struct node
{
	int v,w;
};
vector<node> g[N];
queue<int> q;
int dis[N],n,m,cnt[N],vis[N];
bool spfa()
{
	for(int i=1;i<=n;i++) dis[i]=inf,cnt[i]=vis[i]=0;
	while(!q.empty()) q.pop();
	q.push(1);vis[1]=1;dis[1]=0;
	while(!q.empty())
	{
		int u=q.front();
		q.pop();
		vis[u]=0;
		for(node i:g[u])
		{
			int v=i.v;
			if(dis[v]>dis[u]+i.w)
			{
				dis[v]=dis[u]+i.w;
				if(!vis[v])
				{
					if((++cnt[v])>=n) return 1;
					q.push(v);vis[v]=1;
				}
			}
		}
	}
	return 0;
}
signed main()
{
	int t;
	fin>>t;
	while(t--)
	{
		fin>>n>>m;
		for(int i=1;i<=n;i++) vector<node> ().swap(g[i]);
		for(int i=1;i<=m;i++)
		{
			int u,v,w;
			fin>>u>>v>>w;
			g[u].push_back({v,w});
			if(w>=0) g[v].push_back({u,w});
		}
		if(spfa()) fout<<"YES\n";
		else fout<<"NO\n";
	}
	return 0;
}

点分治

struct node
{
	int v,w;
};
vector<node> g[10010];
int ask[110],siz[10010],root,minn,del[10010];
int sum,ans[110],judge[10000010],d[10010];
int q[10010],dis[10010],cnt=0,n,m;
void get_root(int u,int fa)
{
	int maxx=0;
	siz[u]=1;
	for(auto i:g[u])
	{
		int v=i.v;
		if(del[v] || v==fa) continue;
		get_root(v,u);
		siz[u]+=siz[v];
		maxx=max(maxx,siz[v]);
	}
	maxx=max(maxx,sum-siz[u]);
	if(maxx<minn) minn=maxx,root=u;
}
void get_dis(int u,int fa)
{
	dis[++cnt]=d[u];
	for(node i:g[u])
	{
		int v=i.v;
		if(v==fa || del[v]) continue;
		d[v]=d[u]+i.w;
		get_dis(v,u);
	}
}
void calc(int u)
{
	del[u]=judge[0]=1;
	int p=0;
	for(node i:g[u])
	{
		int v=i.v;
		if(del[v]) continue;
		d[v]=i.w;
		cnt=0;
		get_dis(v,u);
		for(int j=1;j<=cnt;j++)
		{
			for(int k=1;k<=m;k++)
			{
				if(dis[j]<=ask[k])
				{
					ans[k]|=judge[ask[k]-dis[j]];
				}
			}
		}
		for(int j=1;j<=cnt;j++)
		{
			if(dis[j]>1e7) continue;
			judge[dis[j]]=1;
			q[++p]=dis[j];
		}
	}
	for(int i=1;i<=p;i++) judge[q[i]]=0;
}
void devide(int u)
{
	calc(u);
	del[u]=1;
	for(node i:g[u])
	{
		int v=i.v;
		if(del[v]) continue;
		sum=minn=siz[v];
		get_root(v,0);
		devide(root);
	}
}
int main()
{
//	freopen("1.in","r",stdin);
	cin>>n>>m;
	for(int i=1;i<n;i++)
	{
		int u,v,w;
		cin>>u>>v>>w;
		g[u].push_back({v,w});
		g[v].push_back({u,w});
	}
	for(int i=1;i<=m;i++) cin>>ask[i];
	sum=minn=n;
	get_root(1,0);
	get_root(root,0);
	devide(root);
	for(int i=1;i<=m;i++)
	{
		if(ans[i]==1) cout<<"AYE\n";
		else cout<<"NAY\n";
	}
	return 0;
}

点分树

const int N=100010;
int son[N],top[N],d[N],siz[N],f[N],RT,sz,mn,rt,del[N],dfa[N],lstans,n,a[N],cnt=1,h[N];
struct edge
{
	int to,nxt;
} e[N<<1];
void add_edge(int u,int v)
{
	cnt++;
	e[cnt].to=v;e[cnt].nxt=h[u];
	h[u]=cnt;
}
struct Tree
{
	int rt[N],tot;
	struct node
	{
		int sum,lid,rid;
	} t[N*300];
	void push_up(int id)
	{
		t[id].sum=t[t[id].lid].sum+t[t[id].rid].sum;
	}
	void add(int& id,int l,int r,int x,int k)
	{
		if(!id) id=++tot;
		if(l==r)
		{
			t[id].sum+=k;
			return;
		}
		int mid=(l+r)>>1;
		if(x<=mid) add(t[id].lid,l,mid,x,k);
		else add(t[id].rid,mid+1,r,x,k);
		push_up(id);
	}
	int query(int id,int l,int r,int L,int R)
	{
		if(L<=l && r<=R) return t[id].sum;
		int mid=(l+r)>>1,ret=0;
		if(L<=mid) ret+=query(t[id].lid,l,mid,L,R);
		if(R>mid) ret+=query(t[id].rid,mid+1,r,L,R);
		return ret;
	}
} T1,T2;
il void get_son(int u,int fa)
{
	f[u]=fa;d[u]=d[fa]+1;
	siz[u]=1;
//	cout<<u<<"\n";
	for(int i=h[u];i;i=e[i].nxt)
	{
		int v=e[i].to;
		if(v==fa) continue;
		get_son(v,u);
		siz[u]+=siz[v];
		if(siz[v]>siz[son[u]]) son[u]=v;
	}
}
il void get_top(int u,int t)
{
	top[u]=t;
	if(son[u]) get_top(son[u],t);
	for(int i=h[u];i;i=e[i].nxt)
	{
		int v=e[i].to;
		if(v==f[u] || v==son[u]) continue;
		get_top(v,v);
	}
}
il void get_root(int u,int fa)
{
	siz[u]=1;
	int mx=0;
	for(int i=h[u];i;i=e[i].nxt)
	{
		int v=e[i].to;
		if(v==fa || del[v]) continue;
		get_root(v,u);
		siz[u]+=siz[v];
		mx=max(mx,siz[v]);
	}
	mx=max(mx,sz-siz[u]);
	if(mx<mn) mn=mx,rt=u;
}
il int get_dis(int u,int v)
{
	int ret=0;
	while(top[u]!=top[v])
	{
		if(d[top[u]]<d[top[v]]) swap(u,v);
		ret+=d[u]-d[top[u]]+1;
		u=f[top[u]];
	}
	if(d[u]<d[v]) swap(u,v);
	ret+=d[u]-d[v];  
	return ret;
}
il void build(int u)
{
	del[u]=1;
	for(int i=h[u];i;i=e[i].nxt)
	{
		int v=e[i].to;
		if(del[v]) continue;
		mn=sz=siz[v];
		get_root(v,0);
		get_root(rt,0);
		dfa[rt]=u;
		build(rt);
	}
}
il void add(int x,int k)
{
	int now=x;
	while(now)
	{
		T1.add(T1.rt[now],0,n,get_dis(now,x),k);
		if(dfa[now]) T2.add(T2.rt[now],0,n,get_dis(dfa[now],x),k);
		now=dfa[now];
	}
}
il int query(int x,int y)
{
	int now=x,ret=0;
	while(now)
	{
		int d=get_dis(now,x);
		if(d<=y) ret+=T1.query(T1.rt[now],0,n,0,y-d);
		if(!dfa[now]) break;
		d=get_dis(dfa[now],x);
		if(d<=y) ret-=T2.query(T2.rt[now],0,n,0,y-d);
		now=dfa[now];
	}
	return ret;
}
signed main()
{
//	freopen("P6329_1.in","r",stdin);
//	freopen("chj.out","w",stdout);
	int m;fin>>n>>m;
	for(int i=1;i<=n;i++) fin>>a[i];
	for(int i=1;i<n;i++)
	{
		int u,v;fin>>u>>v;
		add_edge(u,v);add_edge(v,u);
	}
	get_son(1,0);
	get_top(1,1);
	sz=mn=n;
	get_root(1,0);get_root(rt,0);
	build(rt);
	for(int i=1;i<=n;i++) add(i,a[i]);
	while(m--)
	{
		int op,x,y;fin>>op>>x>>y;x^=lstans;y^=lstans;
		if(op==0) fout<<(lstans=query(x,y))<<"\n";
		else add(x,y-a[x]),a[x]=y;
	}
	return 0;
}

最小割树

const int N=510,M=1510,inf=1e18;
int d[N],h[N],cur[N],tot,n,m,id[N],S,T,vis[N],tmp[N],ans;
int mn[N][10],f[N][10],Q,dep[N];
struct Node
{
	int v,w;
};
vector<Node> g[N];
queue<int> q;
struct edge
{
	int v,next,w;
} e[M<<2];
struct node
{
	int u,v,w;
} E[M];
void add(int u,int v,int w)
{
	e[tot].next=h[u];
	e[tot].v=v;e[tot].w=w;
	h[u]=tot++;
}
void add_edge(int u,int v,int w)
{
	add(u,v,w);add(v,u,0);
}
bool bfs()
{
	for(int i=1;i<=n;i++) d[i]=0;
	d[S]=1;
	q.push(S);
	while(!q.empty())
	{
		int u=q.front();
		q.pop();
		for(int i=h[u];i!=-1;i=e[i].next)
		{
			int v=e[i].v;
			if(e[i].w>0 && d[v]==0)
			{
				d[v]=d[u]+1;
				q.push(v);
			}
		}
	}
	return d[T]>0;
}
int dfs(int u,int val)
{
	if(u==T) return val;
	for(int& i=cur[u];i!=-1;i=e[i].next)
	{
		int v=e[i].v;
		if(e[i].w>0 && d[v]==d[u]+1)
		{
			int w=dfs(v,min(val,e[i].w));
			if(w>0)
			{
				e[i].w-=w;
				e[i^1].w+=w;
				return w;
			}
		}
	}
	return 0;
}
void Dinic()
{
	for(int i=1;i<=n;i++) h[i]=-1;
	tot=ans=0;
	for(int i=1;i<=m;i++)
	{
		add_edge(E[i].u,E[i].v,E[i].w);
		add_edge(E[i].v,E[i].u,E[i].w);
	}
	while(bfs())
	{
		for(int i=1;i<=n;i++) cur[i]=h[i];
		while(int dd=dfs(S,inf)) ans+=dd;
	}
}
void get_vis(int u)
{
	if(vis[u]) return;
	vis[u]=1;
	for(int i=h[u];i!=-1;i=e[i].next)
	{
		int v=e[i].v;
		if(e[i].w>0 && !(i&1)) get_vis(v);
	}
}
void build(int l,int r)
{
	if(l==r) return;
	S=id[l];T=id[l+1];
	Dinic();
	g[S].push_back({T,ans});
	g[T].push_back({S,ans});
	for(int i=1;i<=n;i++) vis[i]=0;
	get_vis(S);
	int cnt1=0,cnt2=0;
	for(int i=l;i<=r;i++) tmp[i]=id[i];
	for(int i=l;i<=r;i++)
	{
		if(vis[tmp[i]]==1) id[l+(++cnt1)-1]=tmp[i];
		else id[r-(++cnt2)+1]=tmp[i];
	}
	build(l,l+cnt1-1);
	build(r-cnt2+1,r);
}
void get_mn(int u,int fa)
{
	dep[u]=dep[fa]+1;
	f[u][0]=fa;
	for(int i=1;i<=9;i++)
	{
		f[u][i]=f[f[u][i-1]][i-1];
		mn[u][i]=min(mn[u][i-1],mn[f[u][i-1]][i-1]);
	}
	for(auto i:g[u])
	{
		int v=i.v;
		if(v==fa) continue;
		mn[v][0]=i.w;
		get_mn(v,u);
	}
}
int query_mn(int u,int v)
{
	int ret=inf;
	if(dep[u]<dep[v]) swap(u,v);
	for(int i=9;i>=0;i--)
	{
		if(dep[f[u][i]]>=dep[v])
		{
			ret=min(ret,mn[u][i]);
			u=f[u][i];
		}
	}
	if(u==v) return ret;
	for(int i=9;i>=0;i--)
	{
		if(f[u][i]!=f[v][i])
		{
			ret=min(ret,min(mn[u][i],mn[v][i]));
			u=f[u][i],v=f[v][i];
		}
	}
	ret=min(ret,min(mn[u][0],mn[v][0]));
	return ret;
}
signed main()
{
	fin>>n>>m;
	n++;
	for(int i=1;i<=m;i++)
	{
		fin>>E[i].u>>E[i].v>>E[i].w;
		E[i].u++,E[i].v++;
	}
	for(int i=1;i<=n;i++) id[i]=i;
	build(1,n);
	get_mn(1,0);
	fin>>Q;
	while(Q--)
	{
		int u,v;fin>>u>>v;
		u++,v++;
		fout<<query_mn(u,v)<<"\n";
	}
	return 0;
}

树哈希

const int N=60,p=13331,mod=1e9+7;
vector<int> g[N];
int sz,mn,rt,rrt,siz[N],Hash[N],d[N],powp[N];
pair<int,int> f[N],val[N];
il void get_rt(int u,int fa)
{
	siz[u]=1;
	int mx=0;
	for(int v:g[u])
	{
		if(v==fa) continue;
		get_rt(v,u);
		siz[u]+=siz[v];
		mx=max(mx,siz[v]);
	}
	mx=max(mx,sz-siz[u]);
//	fout<<u<<" "<<mx<<"\n";
	if(mx<mn) rt=u,rrt=0,mn=mx;
	else if(mx==mn) rrt=u;
}
il void get_hash(int u,int fa)
{
	d[u]=d[fa]+1;siz[u]=1;
	Hash[u]=d[u];
	for(int v:g[u])
	{
		if(v==fa) continue;
		get_hash(v,u);
	}
	int cnt=0;
	for(int v:g[u])
	{
		if(v==fa) continue;
		val[++cnt]={Hash[v],siz[v]};
	}
	sort(val+1,val+1+cnt);
	for(int i=1;i<=cnt;i++) Hash[u]=(Hash[u]+1ll*powp[siz[u]]*val[i].first)%mod,siz[u]+=val[i].second;
//	fout<<u<<" "<<Hash[u]<<"\n";
}
il void solve(int idx)
{
	int n;fin>>n;
	for(int i=1;i<=n;i++) g[i].clear();
	for(int i=1;i<=n;i++)
	{
		int u;fin>>u;
		if(u) g[u].push_back(i),g[i].push_back(u);
	}
	mn=sz=n;rt=rrt=0;
	get_rt(1,0);
	get_hash(rt,0);f[idx].first=Hash[rt];
	if(rrt) get_hash(rrt,0);f[idx].second=Hash[rrt];
//	fout<<"\n";
	if(f[idx].first>f[idx].second) swap(f[idx].first,f[idx].second);
}
signed main()
{
	powp[0]=1;
	for(int i=1;i<=50;i++) powp[i]=1ll*powp[i-1]*p%mod;
	int m;fin>>m;
	for(int i=1;i<=m;i++) solve(i);
	for(int i=1;i<=m;i++)
	{
		for(int j=1;j<=i;j++)
		{
			if(f[i]==f[j])
			{
				fout<<j<<"\n";
				break;
			}
		}
	}
	return 0;
}

串串

SAM

const int N=1000010;
int tot=1,lst=1,d[N<<1],idx[N];
struct node
{
	int len,cnt,ch[26],fa;
} dian[N<<1];
queue<int> q;
int SAM_add(int p,int c)
{
	int np=++tot;
	dian[np].len=dian[p].len+1;
	while(p && !dian[p].ch[c]) dian[p].ch[c]=np,p=dian[p].fa;
	if(!p) dian[np].fa=1;
	else
	{
		int q=dian[p].ch[c];
		if(dian[q].len==dian[p].len+1) dian[np].fa=q;
		else
		{
			int nq=++tot;dian[nq]=dian[q];
			dian[nq].len=dian[p].len+1;
			dian[np].fa=dian[q].fa=nq;
			while(p && dian[p].ch[c]==q) dian[p].ch[c]=nq,p=dian[p].fa;
		}
	}
	return np;
}
signed main()
{
//	freopen("P3804_2.in","r",stdin);
//	freopen("chj.out","w",stdout);
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	string s;cin>>s;int n=s.size();s=" "+s;
	for(int i=1;i<=n;i++) lst=SAM_add(lst,s[i]-'a'),idx[i]=lst;
	for(int i=1;i<=n;i++) dian[idx[i]].cnt++;
	for(int i=1;i<=tot;i++) d[dian[i].fa]++;
	for(int i=1;i<=tot;i++) if(!d[i]) q.push(i);
	while(!q.empty())
	{
		int u=q.front();q.pop();
		int v=dian[u].fa;d[v]--;
		dian[v].cnt+=dian[u].cnt;
		if(!d[v]) q.push(v);
	}
	long long ans=0;
	for(int i=1;i<=tot;i++)
	{
		if(dian[i].cnt!=1)
		{
			ans=max(ans,1ll*dian[i].cnt*dian[i].len);
		}
	}
	cout<<ans;
	return 0;
}

manacher

const int N=11000010;
int p[N],n;
string s;
signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin>>s;n=s.size();s=" "+s;
	int idx=0,R=0,ans=0;
	for(int i=1;i<=n;i++)
	{
		int k=(i>R)?1:min(R-i+1,p[idx*2-i]);
		while(i-k>=1 && i+k<=n && s[i-k]==s[i+k]) k++;
		p[i]=k;
		if(i+k-1>R) R=i+k-1,idx=i;
		ans=max(ans,p[i]*2-1);
	}
	idx=0,R=0;
	for(int i=1;i<=n;i++)
	{
		int k=(i>R)?0:min(R-i,p[2*idx-i]);
		while(i-k>=1 && i+k+1<=n && s[i-k]==s[i+k+1]) k++;
		p[i]=k;
		if(i+k>R) R=i+k,idx=i;
		ans=max(ans,p[i]*2);
	}
	cout<<ans;
	return 0;
}

SA

const int N=1000010;
string s;
int n,sa[N],rk[N<<1],id[N],oldrk[N<<1],cnt[N],ht[N];
void get_sa()
{
	int m=127,p=0;
	for(int i=1;i<=n;i++) cnt[rk[i]=s[i]]++;
	for(int i=1;i<=m;i++) cnt[i]+=cnt[i-1];
	for(int i=n;i>=1;i--) sa[cnt[rk[i]]--]=i;
	for(int w=1;w<n;w<<=1,m=p)
	{
		int tot=0;
		for(int i=n-w+1;i<=n;i++) id[++tot]=i;
		for(int i=1;i<=n;i++) if(sa[i]>w) id[++tot]=sa[i]-w;
		for(int i=1;i<=m;i++) cnt[i]=0;
		for(int i=1;i<=n;i++) cnt[rk[i]]++;
		for(int i=1;i<=m;i++) cnt[i]+=cnt[i-1];
		for(int i=n;i>=1;i--) sa[cnt[rk[id[i]]]--]=id[i];
		p=0;
		for(int i=1;i<=n;i++) oldrk[i]=rk[i];
		for(int i=1;i<=n;i++)
		{
			if(oldrk[sa[i]]==oldrk[sa[i-1]] && oldrk[sa[i]+w]==oldrk[sa[i-1]+w]) rk[sa[i]]=p;
			else rk[sa[i]]=++p;
		}
		if(p==n) break;
	}
}
il void get_ht()
{
	for(int i=1,k=0;i<=len;i++)
	{
		if(rk[i]==1) continue;
		if(k) k--;
		int j=sa[rk[i]-1];
		while(i+k<=len && j+k<=len && S[i+k]==S[j+k]) k++;
		ht[rk[i]]=k;
	}
	for(int i=1;i<=len;i++) mn[0][i]=ht[i];
	for(int i=1;(1<<i)<=len;i++)
	{
		for(int j=1;j+(1<<i)-1<=len;j++)
		{
			mn[i][j]=min(mn[i-1][j],mn[i-1][j+(1<<(i-1))]);
		}
	}
}
il int lcp(int x,int y)
{
	if(x<1 || x>n || y<1 || y>n) return 0;
    if(x==y) return n-x+1;
	if((x=rk[x])>(y=rk[y])) swap(x,y);
	int k=__lg(y-(x++));
	return min(mn[k][x],mn[k][y-(1<<k)+1]);
}
signed main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	cin>>s;n=s.size();s=" "+s;
	get_sa();
	for(int i=1;i<=n;i++) cout<<sa[i]<<" ";
	return 0;
}

AC自动机

const int N=200010;
int idx[N],d[N],tot,son[N][26],fail[N],ans[N];
queue<int> q;
void get_fail()
{
	for(int i=0;i<26;i++) if(son[0][i]) q.push(son[0][i]);
	while(!q.empty())
	{
		int u=q.front();q.pop();
		for(int i=0;i<26;i++)
		{
			if(son[u][i])
			{
				fail[son[u][i]]=son[fail[u]][i];
				d[fail[son[u][i]]]++;
				q.push(son[u][i]);
			}
			else son[u][i]=son[fail[u]][i];
		}
	}
}
signed main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	int n;cin>>n;
	for(int i=1;i<=n;i++)
	{
		string t;cin>>t;
		int now=0;
		for(int j=0;j<(int)t.size();j++)
		{
			int c=t[j]-'a';
			if(!son[now][c]) son[now][c]=++tot;
			now=son[now][c];
		}
		idx[i]=now;
	}
	get_fail();
	string s;cin>>s;
	int now=0;
	for(int i=0;i<(int)s.size();i++)
	{
		now=son[now][s[i]-'a'];
		ans[now]++;
	}
	for(int i=0;i<=tot;i++) if(!d[i]) q.push(i);
	while(!q.empty())
	{
		int u=q.front();q.pop();
		int v=fail[u];ans[v]+=ans[u];
		d[v]--;
		if(!d[v]) q.push(v);
	}
	for(int i=1;i<=n;i++) cout<<ans[idx[i]]<<"\n";
	return 0;
}

PAM

const int N=500010;
string s;
int tot=1,n,lstans,lst=1;
struct PAM
{
	int ch[26],fail,cnt,len;
} dian[N];
il void ins(int now,int idx)
{
	int c=s[idx]-'a';
	while(idx-dian[now].len-1<1 || s[idx]!=s[idx-dian[now].len-1]) now=dian[now].fail;
	if(dian[now].ch[c])
	{
		lstans=dian[dian[now].ch[c]].cnt;
		lst=dian[now].ch[c];
		return;
	}
	tot++;
	int tmp=dian[now].fail;
	while(idx-dian[tmp].len-1<1 || s[idx]!=s[idx-dian[tmp].len-1]) tmp=dian[tmp].fail;
	dian[tot].fail=dian[tmp].ch[c];
	dian[tot].len=dian[now].len+2;
	dian[tot].cnt=dian[dian[tot].fail].cnt+1;
	lstans=dian[tot].cnt;lst=tot;
	dian[now].ch[c]=tot;
}
signed main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	dian[0].fail=1;dian[1].len=-1;
	fin>>s;s=" "+s;
	for(int i=1;i<(int)s.size();i++)
	{
		s[i]=(s[i]-97+lstans)%26+97;
		ins(lst,i);
		fout<<lstans<<" ";
	}
	return 0;
}

杂项

插头DP

const int N=200010,P=13331;
string vis[20];
struct HashMap
{
	int h[P],nxt[N],tot;
	int key[N],val[N];
	void clear()
	{
		tot=0;
		for(int i=0;i<P;i++) h[i]=0;
	}
	void add(int x,int k)
	{
		int w=x%P;
		for(int i=h[w];i;i=nxt[i])
		{
			if(key[i]==x)
			{
				val[i]+=k;
				return;
			}
		}
		tot++;
		key[tot]=x,val[tot]=k,nxt[tot]=h[w];
		h[w]=tot;
	}
} dp[2];
il int get_w(int x,int k)
{
	return x>>((k-1)<<1)&3;
}
il int ch_w(int x,int k,int v)
{
	return x^(get_w(x,k)<<((k-1)<<1))^(v<<((k-1)<<1));                                                                                 
}
il int get_L(int x,int k)
{
	int sum=1;
	for(int i=k;i>=1;i--)
	{
		int w=get_w(x,i);
		if(w==2) sum++;
		if(w==1) sum--;
		if(sum==0) return i;
	}
	return -1;
}
il int get_R(int x,int k)
{
	int sum=1;
	for(int i=k;i<=13;i++)
	{
		int w=get_w(x,i);
		if(w==1) sum++;
		if(w==2) sum--;
		if(sum==0) return i;
	}
	return -1;
}
signed main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	int n,m,ex=0,ey=0;fin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		fin>>vis[i];vis[i]=" "+vis[i];
		for(int j=1;j<=m;j++)
		{
			if(vis[i][j]=='.') ex=i,ey=j;
		}
	}
	int pre=0,now=1,ans=0;
	dp[pre].add(0,1);
	for(int i=1;i<=n;i++)
	{
		for(int j=0;j<m;j++)
		{
			for(int k=1;k<=dp[pre].tot;k++)
			{
				int s=dp[pre].key[k],val=dp[pre].val[k];
				int x=get_w(s,j+1),y=get_w(s,j+2);
				if(vis[i][j+1]=='*')
				{
					if(!x && !y) dp[now].add(s,val);
				}
				else
				{
					if(!x && !y) dp[now].add(ch_w(ch_w(s,j+1,1),j+2,2),val);
					else if(!x || !y)
					{
						dp[now].add(s,val);
						dp[now].add(ch_w(ch_w(s,j+1,y),j+2,x),val);
					}
					else 
					{
						s=ch_w(ch_w(s,j+1,0),j+2,0);
						if(x==1 && y==2)
						{
							if(i==ex && j+1==ey && !s) ans+=val;
						}
						else if(x==2 && y==1) dp[now].add(s,val);
						else if(x==1 && y==1)
						{
							int idx=get_R(s,j+2);
//							fout<<idx<<" "<<j+2<<"!!!\n";
							if(idx!=-1) dp[now].add(ch_w(s,idx,1),val);
						}
						else
						{
							int idx=get_L(s,j+1);
//							fout<<idx<<" "<<j+1<<"@@@\n";
							if(idx!=-1) dp[now].add(ch_w(s,idx,2),val);
						}
					}
				}
			}
			swap(pre,now);
			dp[now].clear();
		}
		for(int k=1;k<=dp[pre].tot;k++)
		{
			int s=dp[pre].key[k],val=dp[pre].val[k];
			if(get_w(s,m+1)==0) dp[now].add(s<<2,val);
		}
		swap(pre,now);
		dp[now].clear();
	}
	fout<<ans<<"\n";
	return 0;
}

笛卡尔树

const int N=10000010;
int son[N][2],a[N],st[N],tp,n,ansl,ansr;
void build()
{
	for(int i=1;i<=n;i++)
	{
		int now=tp;
		while(tp && a[st[tp]]>a[i]) tp--;
		if(now!=tp) son[i][0]=st[tp+1];
		if(tp) son[st[tp]][1]=i;
		st[++tp]=i;
	}
//	for(int i=1;i<=n;i++) fout<<son[i][0]<<" "<<son[i][1]<<"\n";
}
signed main()
{
	fin>>n;
	for(int i=1;i<=n;i++) fin>>a[i];
	build();
	for(int i=1;i<=n;i++) ansl^=i*(son[i][0]+1),ansr^=i*(son[i][1]+1);
	fout<<ansl<<" "<<ansr;
	return 0;
}

各种反演

1.二项式反演

\[f(n)=\sum_{i=n}^m\binom{i}{n}g(i)\Longleftrightarrow g(n)=\sum_{i=n}^m(-1)^{i-n}\binom{i}{n}f(i) \]

2.斯特林反演

\[f(n)=\sum_{i=n}^{m}\begin{Bmatrix}i\\n\end{Bmatrix}g(i)\Longleftrightarrow g(n)=\sum_{i=n}^m(-1)^{i-n}\begin{bmatrix}i\\n\end{bmatrix}f(i) \]

第一/二类斯特林数有关

\[\begin{aligned} &\begin{Bmatrix}n\\m\end{Bmatrix}=\begin{Bmatrix}n-1\\m-1\end{Bmatrix}+m\begin{Bmatrix}n-1\\m\end{Bmatrix}\\ &\begin{Bmatrix}n\\m\end{Bmatrix}=\sum_{i=0}^m\frac{(-1)^{m-i}i^n}{(m-i)!i!}\\ &\begin{bmatrix}n\\m\end{bmatrix}=\begin{bmatrix}n-1\\m-1\end{bmatrix}+(n-1)\begin{bmatrix}n-1\\m\end{bmatrix} \end{aligned} \]

上升、下降幂有关

\[\begin{aligned} \binom{n}{k}k^{\underline{i}}=\binom{n-i}{k-i}n^{\underline{i}} \end{aligned} \]

幂的互化

\[\begin{aligned} &x^{\overline{n}}\sum_{i=0}^n\begin{bmatrix}n\\i\end{bmatrix}x^i\\ &x^n=\sum_{i=0}^n\begin{Bmatrix}n\\i\end{Bmatrix}(-1)^{n-i}x^{\overline{i}}\\ &x^n=\sum_{i=0}^n\begin{Bmatrix}n\\i\end{Bmatrix}x^{\underline{i}}\\ &x^{\underline{n}}=\sum_{i=0}^n\begin{bmatrix}n\\i\end{bmatrix}(-1)^{n-i}x^i \end{aligned} \]

posted @ 2026-05-01 15:42  stuart220_chen  阅读(7)  评论(0)    收藏  举报