模板

数学

组合数学

快速取模
#define ull unsigned long long 
#define ui128 __uint128_t
struct Barrett{
    ull d;ui128 m;
    void init(ull _d){
        d=_d,m=(((ui128)(1)<<64)/d);
    }
}mod;
ull operator %(ull a,Barrett mod){
    ull w=(mod.m*a)>>64;w=a-w*mod.d;
    if(w>=mod.d)w-=mod.d;return w;
}
光速幂
p1[0]=p2[0]=1,S=sqrt(a)+1;
for(int i=1;i<=S;i++) p1[i]=p1[i-1]*a%mod;
for(int i=1;i<=S;i++) p2[i]=p2[i-1]*p1[S]%mod;
while(T--) cin>>b,cout<<p1[b%S]*p2[b/S]%mod<<" ";
组合数
void init(){jc[0]=1;for(int i=1;i<N;i++) jc[i]=jc[i-1]*i%mod;} 
ll qp(ll a,ll b){ll ct=1;while(b){if(b&1) ct=ct*a%mod;b>>=1,a=a*a%mod;}return ct;}
ll C(ll n,ll m){return jc[n]*qp(jc[n-m]*jc[m]%mod,mod-2)%mod;}
组合数 O(m)
ll qp(ll a,ll b){ll ct=1;while(b){if(b&1) ct=ct*a%mod;b>>=1,a=a*a%mod;}return ct;}
ll C(ll n,ll m){
    ll ct=1,t=1;if(n<m) return 0;
    for(int i=1;i<=m;i++) (ct*=(n-i+1)%mod)%=mod,(t*=i)%=mod;
    return ct*qp(t,mod-2)%mod;
}
组合数(卡常)
ll qp(ll a,ll b){ll ct=1;while(b){if(b&1) ct=ct*a%mod;b>>=1,a=a*a%mod;}return ct;}
ll C(ll m,ll n){return jc[n]*inv[m]%mod*inv[n-m]%mod;}
void init(){
    jc[0]=1;for(int i=1;i<=n;i++) jc[i]=jc[i-1]*i%mod;
	inv[n]=qp(jc[n],mod-2);
	for(int i=n-1;~i;i--) inv[i]=inv[i+1]*(i+1)%mod;
}
lucas
ll T,n,m,p,jc[N],inv[N];
ll Lucas(ll n,ll m,ll p){
	if(n<m) return 0;
	if(n<p) return jc[n]*inv[m]%p*inv[n-m]%p;
	return Lucas(n%p,m%p,p)*Lucas(n/p,m/p,p)%p;
}
ll qp(ll a,ll b,ll ct=1){while(b){if(b&1) ct=ct*a%p;a=a*a%p,b>>=1;}return ct;}
void init(){
	for(int i=1;i<=n+m;i++) jc[i]=jc[i-1]*i%p;
	inv[min(p-1,n+m)]=qp(jc[min(p-1,n+m)],p-2);
	for(int i=min(p-1,n+m)-1;~i;i--) inv[i]=inv[i+1]*(i+1)%p;
}
逆元
for(ll i=2;i<=n;i++) dp[i]=(p-p/i)*dp[p%i]%p;
exgcd
ll T,a,b,c,d,x,y,k,dx,dy;
ll exgcd(ll a,ll b,ll &x,ll &y){
    if(!b){x=1,y=0;return a;}
    ll d=exgcd(b,a%b,y,x);y-=a/b*x;
    return d;
}
void solve(){
	cin>>a>>b>>c;d=exgcd(a,b,x,y);
    if(c%d){cout<<"-1\n";continue;}
    (x*=c)/=d,(y*=c)/=d;
    dx=abs(b/d),dy=abs(a/d),k=ceil((1.0-x)/dx);
    x+=dx*k,y-=dy*k;
    if(y<=0){
        cout<<x<<" ";k=ceil((1.0-y)/dy);
        y+=dy*k,x-=dx*k;
        cout<<y<<"\n";
    }else cout<<(y-1)/dy+1<<" "<<x<<" "<<(y-1)%dy+1<<" "<<x+(y-1)/dy*dx<<" "<<y<<"\n";
}
qp+exgcd+BSGS
map<ll,ll> mp;
ll qp(ll a,ll b,ll ct=1){while(b){if(b&1) ct=ct*a%p;a=a*a%p,b>>=1;}return ct;}
ll exgcd(ll a,ll b,ll &x,ll &y){
    if(!b){x=1,y=0;return a;}
    ll t=exgcd(b,a%b,y,x);y-=a/b*x;return t;
}
void solve2(ll a,ll b,ll p){
	ll t=exgcd(a,p,x,y);p/=t;
	if(!(b%t)) cout<<((x*b/t)%p+p)%p<<"\n";
	else cout<<"Orz, I cannot find x!\n";
}
void BS(ll a,ll b,ll p){for(int i=0;i<=m;i++) mp[b]=i,(b*=a)%=p;}
void GS(ll a,ll b,ll p,ll t=1){
    if(!a&&!b){cout<<"1\n";return;}
    if(!a){cout<<"Orz, I cannot find x!\n";return;}
    ll ct=qp(a,m);
    for(int i=1;i<=m;i++)
        if(mp[(t*=ct)%=p]){cout<<i*m-mp[t]<<"\n";return;}
    cout<<"Orz, I cannot find x!\n";
}
void solve3(ll a,ll b,ll p){a%=p,b%=p,m=ceil(sqrt(p)),mp.clear(),BS(a,b,p),GS(a,b,p);}
excrt
#define i128 __int128
ll n,a,b;
i128 x,y,A=1,B;
i128 exgcd(i128 a,i128 b,i128 &x,i128 &y){
    if(!b){x=1,y=0;return a;}
    ll d=exgcd(b,a%b,y,x);
    y-=a/b*x;return d;
}
ll solve(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a>>b;
        i128 d=exgcd(A,(i128)a,x,y);
        x*=B-b,y*=B-b;x/=d,y/=d;
        B-=A*x,A=A/d*a;((B%=A)+=A)%=A;
    }
    return (ll)((B%A+A)%A);
}
Miller-Rabin+Pollard-Rho
ll T,n,mx;
ll qp(ll a,ll b,ll mod,ll ct=1){while(b){if(b&1) ct=(__int128)ct*a%mod;a=(__int128)a*a%mod;b>>=1;}return ct;}
bool Miller_Rabin(ll x){
    if(x<2) return 0;
    if(x==2||x==3) return 1;
    ll b=x-1,ct=0;
    while(!(b&1)) b>>=1,ct++;
    for(int i=0;i<10;i++){
        ll a=rand()%(x-2)+2,p=qp(a,b,x);
        if(p==1||p==x-1) continue;
        for(int j=1;j<ct;j++){
            p=(__int128)p*p%x;
            if(p==x-1) break;
        }
        if(p!=x-1) return 0;
    }
    return 1;
}
ll Pollard_Rho(ll x){
    ll c=rand()%(x-1)+1;
    for(ll ct=1,s=0,t=0,p=1;;ct*=2,s=t,p=1){
        for(ll i=1;i<=ct;i++){
            t=((__int128)t*t+c)%x;
            p=(__int128)p*abs(t-s)%x;
            if(!(i%127)){
                ll tmp=__gcd(p,x);
                if(tmp>1) return tmp;
            }
        }
        ll tmp=gcd(p,x);
        if(tmp>1) return tmp;
    }
}
void fac(ll x){
    if(x<=mx||x<2) return;
    if(Miller_Rabin(x)){mx=max(mx,x);return;}
    ll ct=x;
    while(ct>=x) ct=Pollard_Rho(x);
    while(!(x%ct)) x/=ct;
    fac(x),fac(ct);
}

线性代数

矩阵快速幂
struct MAT{
	ll a[3][3]={};
	ll* operator[](int x){return a[x];}
	MAT operator*(MAT& b){
		MAT res;
		for(int i=1;i<=2;i++)
			for(int j=1;j<=2;j++)
				for(int k=1;k<=2;k++)
					(res[i][j]+=a[i][k]*b[k][j])%=mod;
		return res;
	}
}a,ans;
void qp(ll b){while(b){if(b&1) ans=ans*a;a=a*a,b>>=1;}}
void init(){a[1][1]=a[1][2]=a[2][1]=ans[1][1]=ans[2][2]=1;}
ll get_ans(ll n){qp(n);return ans[1][2];}
高斯消元
bool solve(){
	for(int i=1;i<=n;i++){
		ll r=i;
		for(int j=i+1;j<=n;j++)
			if(fabs(a[j][i])>fabs(a[r][i])) r=j;
		if(fabs(a[r][i])<eps) return 1;
		if(r!=i) swap(a[i],a[r]);
		double t=a[i][i];
		for(int j=i;j<=n+1;j++) a[i][j]/=t;
		for(int j=i+1;j<=n;j++){
			t=a[j][i];
			for(int k=i;k<=n+1;k++)
				a[j][k]-=a[i][k]*t;
		}
	}
	x[n]=a[n][n+1];
	for(int i=n-1;i>=1;i--){
		x[i]=a[i][n+1];
		for(int j=i+1;j<=n;j++)
			x[i]-=(a[i][j]*x[j]);
	}
	return 0;
}
矩阵求逆
void Gauss(){
	for(int i=1,r;i<=n;i++){
		r=i;
		for(int j=i+1;j<=n;j++)
			if(fabs(a[j][i])>fabs(a[r][i])) r=j;
		if(r!=i) swap(a[r],a[i]);
		if(!a[i][i]){cout<<"No Solution";return;}
		ll t=qp(a[i][i],mod-2);
		for(int j=1;j<=n;j++){
			if(i==j) continue;
			ll q=a[j][i]*t%mod;
			for(int k=i;k<=(n<<1);k++)
				a[j][k]-=a[i][k]*q,a[j][k]%=mod,a[j][k]+=mod,a[j][k]%=mod;
		}
		for(int j=1;j<=(n<<1);j++) a[i][j]*=t,a[i][j]%=mod;
	}
	for(int i=1;i<=n;i++)
		for(int j=n+1;j<=(n<<1);j++)
			cout<<a[i][j]<<(j==(n<<1)?"\n":" ");
}
void init(){for(int i=1;i<=n;i++) a[i][n+1]=1;}
行列式求值
ll solve(){
	ll res=1,kk=1;
	for(int i=1;i<=n;i++)
		for(int j=i+1;j<=n;j++){
			while(a[i][i]){
				ll t=a[j][i]/a[i][i];
				for(int k=i;k<=n;k++) ((a[j][k]-=a[i][k]*t)+=mod)%=mod;
				swap(a[i],a[j]),kk=-kk;
			}
			swap(a[i],a[j]),kk=-kk;
		}
	for(int i=1;i<=n;i++) res*=a[i][i],res%=mod;
	res*=kk,res%=mod,res+=mod,res%=mod;
	return res;
}

数据结构

线段树家族

线段树 1
#define mid (l+r>>1)
#define ls (rt<<1)
#define rs (ls|1)
#define L ls,l,mid
#define R rs,mid+1,r
void up(ll rt){t[rt]=min(t[ls],t[rs]);}
void down(ll rt,ll k){t[rt]+=k,lazy[rt]+=k;}
void push_down(ll rt){if(lazy[rt]) down(ls,lazy[rt]),down(rs,lazy[rt]),lazy[rt]=0;}
void build(ll rt,ll l,ll r){if(l==r){t[rt]=a[l];return;}build(L),build(R),up(rt);}
void add(ll rt,ll l,ll r,ll rl,ll rr,ll k){
    if(rl>r||rr<l) return;
    if(rl<=l&&r<=rr){down(rt,k);return;}
    push_down(rt),add(L,rl,rr,k),add(R,rl,rr,k),up(rt);
}
ll query(ll rt,ll l,ll r,ll rl,ll rr){
    if(rl>r||rr<l) return 1e18;
    if(rl<=l&&r<=rr) return t[rt];
    push_down(rt);return min(query(L,rl,rr),query(R,rl,rr));
}
线段树 2
#define mid (l+r>>1)
#define ls (rt<<1)
#define rs (ls|1)
#define L ls,l,mid
#define R rs,mid+1,r
void up(ll rt){t[rt]=(t[ls]+t[rs])%mod;}
void build(ll rt,ll l,ll r){
	lazy2[rt]=1;if(l==r){t[rt]=a[l];return;}
	build(L),build(R);up(rt);
}
void down(ll rt,ll l,ll r,ll k,ll k2){
	(t[rt]*=k2)%=mod,(t[rt]+=k*(r-l+1)%mod)%=mod;
	(lazy[rt]*=k2)%=mod,(lazy[rt]+=k)%=mod,(lazy2[rt]*=k2)%=mod;
}
void push_down(ll rt,ll l,ll r){down(L,lazy[rt],lazy2[rt]),down(R,lazy[rt],lazy2[rt]),lazy[rt]=0,lazy2[rt]=1;}
void update(ll rt,ll l,ll r,ll rl,ll rr,ll k){
	if(rl>r||rr<l) return;
	if(rl<=l&&r<=rr){(t[rt]+=(r-l+1)*k)%=mod,(lazy[rt]+=k)%=mod;return;}
    push_down(rt,l,r);update(L,rl,rr,k),update(R,rl,rr,k);up(rt);
}
void update2(ll rt,ll l,ll r,ll rl,ll rr,ll k){
	if(rl>r||rr<l) return;
	if(rl<=l&&r<=rr){(t[rt]*=k)%=mod,(lazy[rt]*=k)%=mod,(lazy2[rt]*=k)%=mod;return;}
	push_down(rt,l,r);update2(L,rl,rr,k),update2(R,rl,rr,k);up(rt);
}
ll query(ll rt,ll l,ll r,ll rl,ll rr){
	if(rl>r||rr<l) return 0;
	if(rl<=l&&r<=rr) return t[rt];
	push_down(rt,l,r);return (query(L,rl,rr)+query(R,rl,rr))%mod;
}
动态开点线段树
#define mid (l+r>>1)
#define L t[rt].ls,l,mid
#define R t[rt].rs,mid+1,r
struct Tree{ll ls,rs,val;}t[N];
void up(ll rt){t[rt].val=t[t[rt].ls].val+t[t[rt].rs].val;}
void down(ll rt,ll l,ll r,ll k){lazy[rt]=k,t[rt].val=(r-l+1)*k;}
void push_down(ll rt,ll l,ll r){if(~lazy[rt]) down(L,lazy[rt]),down(R,lazy[rt]),lazy[rt]=-1;}
void update(ll rt,ll l,ll r,ll rl,ll rr,ll k){
	if(rl>r||rr<l) return;
	if(rl<=l&&r<=rr){down(rt,l,r,k);return;}
	if(!t[rt].ls) t[rt].ls=++ct;if(!t[rt].rs) t[rt].rs=++ct;
	push_down(rt,l,r);
	update(L,rl,rr,k);update(R,rl,rr,k);up(rt);
}
线段树-区间加 区间求 gcd
#define mid (l+r>>1)
#define ls (rt<<1)
#define rs (ls|1)
#define L ls,l,mid
#define R rs,mid+1,r
void up(ll rt){t[rt]=__gcd(t[ls],t[rs]),s[rt]=s[ls]+s[rs];}
void build(ll rt,ll l,ll r){
    if(l==r){t[rt]=s[rt]=a[l]-a[l-1];return;}
    build(L),build(R),up(rt);
}
void update(ll rt,ll l,ll r,ll x,ll d){
    if(l>x||r<x) return;
    if(l==r){t[rt]+=d,s[rt]+=d;return;}
    update(L,x,d),update(R,x,d),up(rt);
}
ll query(ll rt,ll l,ll r,ll rl,ll rr){
    if(rl>r||rr<l) return 0;
    if(rl<=l&&r<=rr) return t[rt];
    return __gcd(query(L,rl,rr),query(R,r,rl,rr));
}
ll sum(ll rt,ll l,ll r,ll rl,ll rr){
    if(rl>r||rr<l) return 0;
    if(rl<=l&&r<=rr) return s[rt];
    return sum(L,rl,rr)+sum(R,rl,rr);
}
void upd(ll l,ll r,ll d){update(1,1,n,l,d),update(1,1,n,r+1,-d);}
ll qry(ll l,ll r){return abs(__gcd(query(1,1,n,l+1,r),sum(1,1,n,1,l)));}
线段树-区间赋值 区间覆盖 区间求和
#define mid (l+r>>1)
#define ls (rt<<1)
#define rs (ls|1)
#define L ls,l,mid
#define R rs,mid+1,r
void up(ll rt){t[rt]=t[ls]+t[rs];}
void push_down(ll rt,ll l,ll r){
	if(~lazy2[rt]){
        t[ls]=lazy2[rt]*(mid-l+1);
        t[rs]=lazy2[rt]*(r-mid);
		lazy2[ls]=lazy2[rs]=lazy2[rt];
		lazy[ls]=lazy[rs]=0,lazy2[rt]=-1;
	}
	if(lazy[rt]){
		lazy[ls]^=1,lazy[rs]^=1;
        t[ls]=mid-l+1-t[ls],t[rs]=r-mid-t[rs];
		lazy[rt]=0;
	}
}
void update(ll rt,ll l,ll r,ll rl,ll rr){
	if(rl>r||rr<l) return;
	if(rl<=l&&r<=rr){lazy[rt]^=1;t[rt]=r-l+1-t[rt];return;}
	push_down(rt,l,r);update(L,rl,rr),update(R,r,rl,rr);up(rt);
}
void cover(ll rt,ll l,ll r,ll rl,ll rr,ll k){
	if(rl>r||rr<l) return;
	if(rl<=l&&r<=rr){t[rt]=(r-l+1)*k;lazy2[rt]=k,lazy[rt]=0;return;}
	push_down(rt,l,r);cover(L,rl,rr,k),cover(R,rl,rr,k);up(rt);
}
ll query(ll rt,ll l,ll r){
	if(l==r) return l;
	push_down(rt,l,r);
	if(t[rt<<1]<mid-l+1) return query(L);
    return query(R);
}
void init(){memset(lazy2,-1,sizeof lazy2);}
线段树分治
#define mid (l+r>>1)
#define ls (rt<<1)
#define rs (ls|1)
#define L ls,l,mid
#define R rs,mid+1,r
void init(){for(int i=1;i<=n*2;i++) fa[i]=i,sz[i]=1;}
ll getfa(ll x){return fa[x]==x?x:getfa(fa[x]);}
void hb(ll x,ll y){
    ll fx=getfa(x),fy=getfa(y);
    if(fx==fy) return;
    if(sz[fx]>sz[fy]) fx^=fy^=fx^=fy;
    s.push({fx,sz[fx]==sz[fy]});fa[fx]=fy,sz[fy]+=(sz[fx]==sz[fy]);
}
void update(ll rt,ll l,ll r,ll rl,ll rr,ll k){
    if(rl>r||rr<l) return;
    if(rl<=l&&r<=rr){t[rt].push_back(k);return;}
    update(L,rl,rr,k),update(R,rl,rr,k);
}
void dfs(ll rt,ll l,ll r){
    bool flag=1;ll lst=s.size();
    for(auto i:t[rt]){
        ll fx=getfa(x[i]),fy=getfa(y[i]);
        if(fx==fy){
            for(int i=l;i<=r;i++) cout<<"No\n";
            flag=0;
            break;
        }
        hb(x[i],y[i]+n),hb(y[i],x[i]+n);
    }
    if(flag){
        if(l==r) cout<<"Yes\n";
        else dfs(L),dfs(R);
    }
    while(s.size()>lst) sz[fa[s.top().fi]]-=s.top().se,fa[s.top().fi]=s.top().fi,s.pop();
}
线段树优化建图
#define mid (l+r>>1)
#define ls (rt<<1)
#define rs (ls|1)
#define L ls,l,mid
#define R rs,mid+1,r
void Add(ll x,ll y,ll w=0){e[x].pb(y,(~w?w:0));if(!~w) Add(y,x);}
void build(ll rt,ll l,ll r){
	if(l==r){leaf[l]=rt;return;}
	Add(rt,ls),Add(rt,rs);
	Add(ls+P,rt+P),Add(rs+P,rt+P);
	build(L),build(R);
}
void add(ll rt,ll l,ll r,ll rl,ll rr,ll v,ll w,ll op){
	if(rl>r||rr<l) return;
	if(rl<=l&&r<=rr){
		if(op) Add(rt+P,v,w);
		else Add(v,rt,w);
		return;
	}
	add(L,rl,rr,v,w,op),add(R,rl,rr,v,w,op);
}
void dijkstra(){
	priority_queue<pii,vector<pii>,greater<pii> > q;
	memset(dis,0x3f,sizeof dis);
	q.push({dis[leaf[s]+P]=0,leaf[s]+P});
	while(!q.empty()){
		ll x=q.top().se;q.pop();
		if(vis[x]) continue;
		vis[x]=1;
		for(auto p:e[x]){
			ll y=p.fi,w=p.se;
			if(dis[y]>dis[x]+w) q.push({dis[y]=dis[x]+w,y});
		}
	}
}
void solve(){
	cin>>n>>q>>s;build(1,1,n);
	while(q--){
		cin>>op>>v;
		if(op==1) cin>>u>>w,Add(leaf[v],leaf[u],w);
		else cin>>l>>r>>w,add(1,1,n,l,r,leaf[v],w,op&1);
	}
	for(int i=1;i<=n;i++) Add(leaf[i],leaf[i]+P,-1);
	dijkstra();
	for(int i=1;i<=n;i++) cout<<(dis[leaf[i]]==inf?-1:dis[leaf[i]])<<" ";
}
扫描线
#define mid (l+r>>1)
#define ls (rt<<1)
#define rs (ls|1)
#define L ls,l,mid
#define R rs,mid,r
// 上一行注意!
struct P{ll h,x,y,op;bool operator<(const P& b){return h==b.h?x>b.x:h<b.h;}}p[N];
struct Q{ll s,l;}tree[N];// 开大一点!!!
void up(ll rt,ll l,ll r){
	if(tree[rt].s>0) tree[rt].l=y[r]-y[l];
	else tree[rt].l=tree[ls].l+tree[rs].l;
}
void change(ll rt,ll l,ll r,ll rl,ll rr,ll k){
	if(rl>=y[r]||y[l]>=rr) return;
	if(rl<=y[l]&&y[r]<=rr){tree[rt].s+=k,up(rt,l,r);return;}
	change(L,rl,rr,k),change(R,rl,rr,k),up(rt,l,r);
}
void solve(){
	cin>>n;n<<=1;
	for(int i=1;i<n;i+=2){
		cin>>sx>>sy>>ex>>ey;
		p[i]={sx,sy,ey,1},p[i+1]={ex,sy,ey,-1};
		y[i]=sy,y[i+1]=ey;
	}
	sort(y+1,y+n+1),sort(p+1,p+n+1);
	for(int i=1;i<=n;i++)
		if(y[i]!=y[i+1]) y[++ct]=y[i];
	for(int i=1;i<n;i++)
		change(1,1,ct,p[i].x,p[i].y,p[i].op),ans+=(p[i+1].h-p[i].h)*tree[1].l;
	cout<<ans;
}
树状数组 1
#define lowbit(x) (x)&(-(x))
void xg(ll x,ll k){while(x<=n) s[x]+=k,x+=lowbit(x);}
ll sum(ll x,ll ct=0){while(x) ct+=s[x],x-=lowbit(x);return ct;}
ll getsum(ll l,ll r){return sum(r)-sum(l-1);}
树状数组 2
void xg(ll s[],ll x,ll k){while(x<=n) s[x]+=k,x+=lowbit(x);}
void qxg(ll x,ll y,ll k){xg(s,x,k);xg(s,y+1,-k);xg(s2,x,x*k);xg(s2,y+1,-(y+1)*k);}
ll sum(ll s[],ll x,ll ct=0){while(x) ct+=s[x],x-=lowbit(x);return ct;}
ll getsum(ll l,ll r){return (r+1)*sum(s,r)-sum(s2,r)-l*sum(s,l-1)+sum(s2,l-1);}
Treap
#define ls t[rt].son[0]
#define rs t[rt].son[1]
struct T{ll val,data,sz,cnt,son[2];}t[N];
ll New(ll x){t[++ct].val=x,t[ct].data=rand(),t[ct].sz=t[ct].cnt=1;return ct;}
void up(ll rt){t[rt].sz=t[ls].sz+t[rs].sz+t[rt].cnt;}
void rot(ll &rt,bool d){
	int p=t[rt].son[!d];t[rt].son[!d]=t[p].son[d],t[p].son[d]=rt,rt=p;
	up(t[rt].son[d]),up(rt);
}
void insert(ll &rt,ll x){
	if(!rt){rt=New(x);return;}
	if(t[rt].val==x){t[rt].cnt++,up(rt);return;}
	bool d=(x>t[rt].val);insert(t[rt].son[d],x);
	if(t[rt].data<t[t[rt].son[d]].data) rot(rt,!d);
	up(rt);
}
void del(ll &rt,ll x){
	if(!rt) return;
	if(t[rt].val==x){
		if(t[rt].cnt>1){t[rt].cnt--;up(rt);return;}
		if(ls||rs){
			if(!rs||t[ls].data>t[rs].data) rot(rt,1),del(rs,x);
			else rot(rt,0),del(ls,x);
			up(rt);
		}else rt=0;
		return;
	}
	if(x<t[rt].val) del(ls,x);
	else del(rs,x);
	up(rt);
}
ll rnk(ll rt,ll x){
	if(!rt) return 1;
	if(t[rt].val==x) return t[ls].sz+1;
	if(t[rt].val>x) return rnk(ls,x);
	return t[ls].sz+t[rt].cnt+rnk(rs,x);
}
ll search(ll rt,ll x){
	if(!rt) return inf;
	if(x<=t[ls].sz) return search(ls,x);
	if(x<=t[ls].sz+t[rt].cnt) return t[rt].val;
	return search(rs,x-t[ls].sz-t[rt].cnt);
}
ll pre(ll x){
	ll rt=root,p=0;
	while(rt)
		if(t[rt].val<x) p=t[rt].val,rt=rs;
		else rt=ls;
	return p;
}
ll nxt(ll x){
	ll rt=root,p=0;
	while(rt)
		if(t[rt].val>x) p=t[rt].val,rt=ls;
		else rt=rs;
	return p;
}
splay
ll ct,rt;
struct T{ll sz,fa,key,son[2];}t[N];
#define ls(x) t[x].son[0]
#define rs(x) t[x].son[1]
#define son(x,p) t[x].son[p]
#define fa(x) t[x].fa
#define key(x) t[x].key
#define sz(x) t[x].sz
ll New(ll x){ct++,key(ct)=x,sz(ct)=1;return ct;}
void up(ll x){sz(x)=sz(ls(x))+sz(rs(x))+1;}
bool getd(ll x,ll y){return x==rs(y);}
void clr(ll x){ls(x)=rs(x)=fa(x)=key(x)=sz(x)=0;}
void rot(ll x){
    ll y=fa(x),z=fa(y);bool d=getd(x,fa(x));
    if(son(x,d^1)) fa(son(x,d^1))=y;
    son(y,d)=son(x,d^1),son(x,d^1)=y;fa(x)=z,fa(y)=x;
    if(z) son(z,getd(y,z))=x;
    up(y),up(x);
}
void splay(ll x){
    for(int i;i=fa(x);rot(x))
        if(fa(i)) rot(getd(x,fa(x))==getd(i,fa(i))?i:x);
    rt=x;
}
void insert(ll x){
    ll y=rt,lst=0;
    while(y) lst=y,y=son(y,x>key(y));
    y=New(x),fa(y)=lst,son(lst,x>key(lst))=y;
    splay(y);
}
void del(ll x){
    ll y=rt,lst=0,p;
    while(y&&key(y)!=x) lst=y,y=son(y,x>key(y));
    if(!y){splay(lst);return;}
    splay(y);p=ls(y);
    if(!p){fa(rt=rs(y))=0,clr(y);return;}
    while(rs(p)) p=rs(p);
    rs(p)=rs(y),fa(rs(y))=p,fa(ls(y))=0;clr(y);
    up(p),splay(p);
}
ll rk(ll x,ll res=1){
    ll y=rt,lst=0;
    while(y) lst=y,res+=(x>key(y))*(sz(ls(y))+1),y=son(y,x>key(y));
    splay(lst);return res;
}
ll kth(ll x){
    ll y=rt;
    while(y)
        if(sz(ls(y))+1<x) x-=sz(ls(y))+1,y=rs(y);
        else if(sz(ls(y))+1==x) break;
        else y=ls(y);
    splay(y);return key(y);
}
ll pre(ll x){
    ll y=rt,lst=0,p=0;
    while(y){
        lst=y;
        if(x>key(y)) p=key(y);
        y=son(y,x>key(y));
    }
    splay(lst);return p;
}
ll nxt(ll x){
    ll y=rt,lst=0,p=0;
    while(y){
        lst=y;
        if(x<key(y)) p=key(y);
        y=son(y,x>=key(y));
    }
    splay(lst);return p;
}
主席树
#define mid (l+r>>1)
ll n,m,p,l,r,k,ct,a[N],b[N],rt[N];
struct T{ll ls,rs,val;}t[N<<5];
ll build(ll l,ll r){
    ll rt=++ct;if(l==r) return rt;
    t[rt].ls=build(l,mid),t[rt].rs=build(mid+1,r);
    return rt;
}
ll mk(ll x){t[++ct]=t[x];return ct;}
ll update(ll rt,ll l,ll r,ll x){
    if(l>x||r<x) return rt;
    rt=mk(rt),t[rt].val++;
    if(l==r) return rt;
    t[rt].ls=update(t[rt].ls,l,mid,x),t[rt].rs=update(t[rt].rs,mid+1,r,x);
    return rt;
}
ll query(ll rt,ll rt2,ll l,ll r,ll x){
    if(l==r) return l;
    ll tmp=t[t[rt2].ls].val-t[t[rt].ls].val;
    if(x<=tmp) return query(t[rt].ls,t[rt2].ls,l,mid,x);
    return query(t[rt].rs,t[rt2].rs,mid+1,r,x-tmp);
}
void init(){
	for(int i=1;i<=n;i++) b[i]=a[i];
    sort(b+1,b+n+1);p=unique(b+1,b+n+1)-b-1;
    for(int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+p+1,a[i])-b;
    rt[0]=build(1,p);for(int i=1;i<=n;i++) rt[i]=update(rt[i-1],1,p,a[i]);
}
ll qry(ll l,ll r){return b[query(rt[l-1],rt[r],1,p,k)];}
李超线段树
#define mid (l+r>>1)
#define ls (rt<<1)
#define rs (ls|1)
#define L ls,l,mid
#define R rs,mid+1,r
bool check(pii a,pii b){
    if(abs(a.fi-b.fi)>eps) return a.fi-b.fi>eps;
    return a.se>b.se;
}
db calc(ll i,ll x){return k[i]*x+b[i];}
void upd(ll rt,ll l,ll r,ll i){
    if(check({calc(i,mid),t[rt]},{calc(t[rt],mid),i})) swap(i,t[rt]);
    if(check({calc(i,l),t[rt]},{calc(t[rt],l),i})) upd(L,i);
    if(check({calc(i,r),t[rt]},{calc(t[rt],r),i})) upd(R,i);
}
void update(ll rt,ll l,ll r,ll rl,ll rr,ll i){
    if(rl>r||rr<l) return;
    if(rl<=l&&r<=rr){upd(rt,l,r,i);return;}
    update(L,rl,rr,i),update(R,rl,rr,i);
}
pii query(ll rt,ll l,ll r,ll x){
    if(l>x||r<x) return {0,-m2};
    if(l==r) return {calc(t[rt],x),-t[rt]};
    return max({{calc(t[rt],x),-t[rt]},query(L,x),query(R,x)});
}
lct
ll n,m,op,x,y;
struct T{ll sz,fa,key,tag,son[2];}t[N];
#define ls(x) t[x].son[0]
#define rs(x) t[x].son[1]
#define son(x,p) t[x].son[p]
#define fa(x) t[x].fa
#define key(x) t[x].key
#define sz(x) t[x].sz
#define tag(x) t[x].tag
void up(ll x){sz(x)=sz(ls(x))^sz(rs(x))^key(x);}
bool getd(ll x){return x==rs(fa(x));}
bool isrt(ll x){return ls(fa(x))!=x&&rs(fa(x))!=x;}
void push_down(ll x){if(tag(x)) swap(ls(x),rs(x)),tag(ls(x))^=1,tag(rs(x))^=1,tag(x)=0;}
void update(ll x){if(!isrt(x)) update(fa(x));push_down(x);}
void rot(ll x){
    ll y=fa(x),z=fa(y);bool d=getd(x);
    if(!isrt(y)) son(z,getd(y))=x;
    fa(son(x,d^1))=y;son(y,d)=son(x,d^1),son(x,d^1)=y;fa(x)=z,fa(y)=x;
    up(y),up(x);
}
void splay(ll x){
    update(x);
    for(int i;i=fa(x),!isrt(x);rot(x))
        if(!isrt(i)) rot(getd(x)==getd(i)?i:x);
}
void access(ll x,ll lst=0){
    while(x){
        splay(x),rs(x)=lst;
        lst=x;up(x);x=fa(x);
    }
}
void mkrt(ll x){access(x),splay(x),tag(x)^=1;}
ll fd(ll x){
    access(x),splay(x),push_down(x);
    while(ls(x)) x=ls(x),push_down(x);
    splay(x);return x;
}
void split(ll x,ll y){mkrt(x),access(y),splay(y);}
void link(ll x,ll y){mkrt(x);if(fd(y)!=x) fa(x)=y;}
void cut(ll x,ll y){mkrt(x);if(fd(y)==x&&fa(y)==x&&!ls(y)) fa(y)=rs(x)=0;}

暴力数据结构

带修莫队
struct Q{
    ll x,y,i,pos,posy,t;
    bool operator<(const Q& B){return pos!=B.pos?pos<B.pos:(posy!=B.posy?posy<B.posy:t<B.t);}
}q[N],g[N];
void add(ll x){res+=!cnt[x]++;}
void del(ll x){res-=!--cnt[x];}
void Mo(ll x,ll y){
    while(l>x) add(a[--l]);
    while(r<y) add(a[++r]);
    while(l<x) del(a[l++]);
    while(r>y) del(a[r--]);
}
void up(ll x,ll y,ll t){
    if(x<=g[t].x&&g[t].x<=y) del(a[g[t].x]),add(g[t].y);
    swap(a[g[t].x],g[t].y);
}
void xg(ll k,ll x,ll y){
    while(t<k) up(x,y,++t);
    while(t>k) up(x,y,t--);
}
回滚莫队
ll n,m,S,tot,res,a[N],t[N],ans[N],l,r,L[N],R[N],tl[N],tr[N];
bool vis[N];
struct Q{ll x,y,i,pos;bool operator<(const Q& B){return pos!=B.pos?pos<B.pos:y<B.y;}}q[N];
void add(ll x){L[a[x]]=min(L[a[x]],x),R[a[x]]=max(R[a[x]],x),res=max(res,R[a[x]]-L[a[x]]);}
void solve(){
	cin>>n;S=sqrt(n);
    for(int i=1;i<=n;i++) cin>>a[i],t[++tot]=a[i];
    sort(t+1,t+tot+1);tot=unique(t+1,t+tot+1)-t-1;
    for(int i=1;i<=n;i++) a[i]=lower_bound(t+1,t+tot+1,a[i])-t;
    cin>>m;for(int i=1;i<=m;i++) cin>>l>>r,q[i]={l,r,i,(l-1)/S+1};
    sort(q+1,q+m+1);memset(tl,0x3f,sizeof tl);
    for(int i=1,j=1;i<=(n-1)/S+1&&j<=m;i++){
        r=min(i*S,n),res=0;
        memset(L,0x3f,sizeof L);
        memset(R,0,sizeof R);
        while(q[j].pos==i){
            l=min(i*S,n)+1;
            if(q[j].y-q[j].x<=S){
                for(ll k=q[j].x;k<=q[j].y;k++)
                    tl[a[k]]=min(tl[a[k]],k),tr[a[k]]=max(tr[a[k]],k),ans[q[j].i]=max(ans[q[j].i],tr[a[k]]-tl[a[k]]);
                for(int k=q[j].x;k<=q[j].y;k++) tl[a[k]]=n,tr[a[k]]=0;
                j++;continue;
            }
            while(r<q[j].y) add(++r);
            ll tmp=res;
            while(l>q[j].x){
                --l;
                if(!vis[a[l]]) vis[a[l]]=1,tl[a[l]]=L[a[l]],tr[a[l]]=R[a[l]];
                add(l);
            }
            ans[q[j].i]=res,res=tmp;
            while(l<=min(i*S,n)){if(vis[a[l]]) vis[a[l]]=0,L[a[l]]=tl[a[l]],R[a[l]]=tr[a[l]],tl[a[l]]=n,tr[a[l]]=0;l++;}
            j++;
        }
    }
    for(int i=1;i<=m;i++) cout<<ans[i]<<"\n";
}

其他

st 表
void init(){
	for(int j=1;(1<<j)<=n;j++)
		for(int i=1;i+(1<<j)-1<=n;i++)
			st[i][j]=max(st[i][j-1],st[i+(1<<j-1)][j-1]);
}
ll query(ll l,ll r){
	ll k=log2(r-l+1);
	return max(st[l][k],st[r-(1<<k)+1][k]); 
}
Trie
void insert(string s){
	ll x=0;
	for(auto c:s){
		if(!trie[x][c]) trie[x][c]=++ct;
		x=trie[x][c],tot[x]++;
	}
}
ll query(string s){
	ll x=0;
	for(auto c:s){
		if(!trie[x][c]) return 0;
		x=trie[x][c];
	}
	return tot[x];
}
void init(){
	for(int i=0;i<=ct;i++)
		for(int j=0;j<128;j++) trie[i][j]=0;
	for(int i=0;i<=ct;i++) tot[i]=0;
	ct=0;
}
笛卡尔树
void build(){
	s[1]=top=1;
	for(int i=2;i<=n;i++){
		while(top&&a[i]<a[s[top]]) top--;
		if(!top) ls[i]=s[1];
		else ls[i]=rs[s[top]],rs[s[top]]=i;
		s[++top]=i;
	}
}
整体二分
#define lowbit(x) (x&-x)
ll n,m,x,ans[N],t[N];
struct Q{ll l,r,k,i;}q[N];
struct A{ll x,i;}a[N];
void add(ll x,ll k){while(x<=n) t[x]+=k,x+=lowbit(x);}
ll query(ll x,ll ct=0){while(x) ct+=t[x],x-=lowbit(x);return ct;}
void solve(ll l,ll r,ll lq,ll la,Q q[],A a[]){
    if(!lq) return;
    if(l==r){for(int i=1;i<=lq;i++) ans[q[i].i]=l;return;}
    Q q1[N],q2[N];A a1[N],a2[N];
    ll mid=(l+r)>>1,lq1=0,lq2=0,la1=0,la2=0;
    for(int i=1;i<=la;i++)
        if(a[i].x<=mid) add(a[i].i,1),a1[++la1]=a[i];
        else a2[++la2]=a[i];
    for(int i=1;i<=lq;i++)
        if(query(q[i].r)-query(q[i].l-1)>=q[i].k) q1[++lq1]=q[i];
        else q[i].k-=query(q[i].r)-query(q[i].l-1),q2[++lq2]=q[i];
    for(int i=1;i<=la1;i++) add(a1[i].i,-1);
    solve(l,mid,lq1,la1,q1,a1);
    solve(mid+1,r,lq2,la2,q2,a2);
}

图论/树论

tarjan 系列

缩点
void tarjan(ll x){
    dfn[x]=low[x]=++ct;s.push(x),vis[x]=1;
    for(auto y:e[x])
        if(!dfn[y]) tarjan(y),low[x]=min(low[x],low[y]);
        else if(vis[y]) low[x]=min(low[x],dfn[y]);
    if(dfn[x]==low[x]){
        tot++;
        while(s.top()!=x) belong[s.top()]=tot,sz[tot]++,vis[s.top()]=0,s.pop();
        s.pop(),vis[x]=0,belong[x]=tot,sz[tot]++;
    }
}
割点
void tarjan(ll x,ll fa,ll rt,ll s=0){
	dfn[x]=low[x]=++ct;
	for(auto y:e[x]){
		if(y==fa) continue;
		if(!dfn[y]){
			s++;tarjan(y,x,rt);low[x]=min(low[x],low[y]);
			if(x!=rt&&low[y]>=dfn[x]) ans+=!ok[x],ok[x]=1;
		}else if(dfn[y]<dfn[x]) low[x]=min(low[x],dfn[y]);
	}
	if(x==rt&&s>=2) ans+=!ok[x],ok[x]=1;
}
点双
void tarjan(ll x,ll fa,ll rt,ll son=0){
	low[x]=dfn[x]=++ct;s[++top]=x;
	for(auto y:e[x])
		if(!dfn[y]){
			son++,tarjan(y,x,rt),low[x]=min(low[x],low[y]);
			if(low[y]>=dfn[x]){
				ans++;
				do{
					p[ans].pb(s[top--]);
				}while(s[top+1]!=y);
				p[ans].pb(x);
			}
		}else if(dfn[y]<dfn[x]&&y!=fa) low[x]=min(low[x],dfn[y]);
	if(x==rt&&!son) p[++ans].pb(x);
}
边双
void tarjan(ll x,ll fa){
	dfn[x]=low[x]=++ct,s[++top]=x;
	for(int i=h[x];i;i=nxt[i]){
		if((~fa)&&i==(fa^1)) continue;
		if(!dfn[to[i]]) tarjan(to[i],i),low[x]=min(low[x],low[to[i]]);
		else low[x]=min(low[x],dfn[to[i]]);
	}
	if(dfn[x]==low[x]){
		tot++;
		while(s[top+1]!=x) p[tot].push_back(s[top--]);
	}
}

网络流

网络最大流
ll n,m,S,T,u,v,w,ct=1,ans,h[N],d[N],now[N];
struct P{ll to,nxt,w;}e[N];
void add(ll x,ll y,ll w,bool p=1){e[++ct]={y,h[x],w},h[x]=ct;if(p) add(y,x,0,0);}
bool bfs(){
    memset(d,-1,sizeof d);
    queue<ll> q;q.push(S),d[S]=0,now[S]=h[S];
    while(!q.empty()){
        ll x=q.front();q.pop();
        for(int i=h[x];i;i=e[i].nxt)
            if(e[i].w&&!~d[e[i].to]){
                d[e[i].to]=d[x]+1,q.push(e[i].to),now[e[i].to]=h[e[i].to];
                if(e[i].to==T) return 1;
            }
    }
    return 0;
}
ll dfs(ll x,ll f,ll res=0){
    if(x==T) return f;
    for(int i=now[x];i&&f;i=e[i].nxt){
        now[x]=i;
        if(e[i].w&&d[e[i].to]==d[x]+1){
            ll t=dfs(e[i].to,min(f,e[i].w));
            if(t) e[i].w-=t,e[i^1].w+=t,res+=t,f-=t;
            else d[e[i].to]=-1;
        }
    }
    return res;
}
ll dinic(ll ct=0){while(bfs()) ct+=dfs(S,inf);return ct;}
最小费用最大流
ll n,S,T,ct=1,mincost,h[N],d[N],now[N];
bool vis[N];
struct P{ll to,nxt,w,c;}e[N];
void add(ll x,ll y,ll w,ll c,bool p=1){e[++ct]={y,h[x],w,c},h[x]=ct;if(p) add(y,x,0,-c,0);}
bool spfa(){
    queue<ll> q;q.push(S);
    for(int i=0;i<=T;i++) d[i]=1e9,vis[i]=0,now[i]=h[i];d[S]=0,vis[S]=1;
    while(q.size()){
        ll x=q.front();q.pop();vis[x]=0;
        for(int i=h[x];i;i=e[i].nxt)
            if(d[e[i].to]>d[x]+e[i].c&&e[i].w){
                d[e[i].to]=d[x]+e[i].c;
                if(!vis[e[i].to]) q.push(e[i].to),vis[e[i].to]=1;
            }
    }
    return d[T]!=1e9;
}
ll dfs(ll x,ll f,ll ct=0){
    if(x==T) return f;
    vis[x]=1;
    for(int i=now[x];i&&f;i=e[i].nxt){
        now[x]=i;
        if(!vis[e[i].to]&&e[i].w&&d[e[i].to]==d[x]+e[i].c){
            ll t=dfs(e[i].to,min(f,e[i].w));
            if(!t) d[e[i].to]=1e9;
            else e[i].w-=t,e[i^1].w+=t,f-=t,ct+=t,mincost+=t*e[i].c;
        }
    }
    vis[x]=0;
    return ct;
}
ll dinic(){while(spfa()) dfs(S,1e9);return mincost;}
无源汇有上下界可行流
ll n,m,x,y,wl,wr,ct=1,tot,S,T,h[N],a[N],l[M],now[N],d[N];
struct P{ll to,nxt,w;}e[M];
void add(ll x,ll y,ll w,bool p=1){e[++ct]={y,h[x],w},h[x]=ct;if(p) add(y,x,0,0);}
bool bfs(){
    memset(d,-1,sizeof d);
    queue<ll> q;q.push(S),d[S]=0,now[S]=h[S];
    while(!q.empty()){
        ll x=q.front();q.pop();
        for(int i=h[x];i;i=e[i].nxt)
            if(e[i].w&&!~d[e[i].to]){
                d[e[i].to]=d[x]+1,q.push(e[i].to),now[e[i].to]=h[e[i].to];
                if(e[i].to==T) return 1;
            }
    }
    return 0;
}
ll dfs(ll x,ll f,ll res=0){
    if(x==T) return f;
    for(int i=now[x];i&&f;i=e[i].nxt){
        now[x]=i;
        if(e[i].w&&d[e[i].to]==d[x]+1){
            ll t=dfs(e[i].to,min(f,e[i].w));
            if(t) e[i].w-=t,e[i^1].w+=t,res+=t,f-=t;
            else d[e[i].to]=-1;
        }
    }
    return res;
}
ll dinic(ll ct=0){while(bfs()) ct+=dfs(S,inf);return ct;}
void solve(){
	cin>>n>>m;T=n+1;
    for(int i=1;i<=m;i++) cin>>x>>y>>wl>>wr,add(x,y,wr-wl),l[ct]=wl,a[x]-=wl,a[y]+=wl;
    for(int i=1;i<=n;i++)
        if(a[i]>0) add(S,i,a[i]),tot+=a[i];
        else add(i,T,-a[i]);
    if(dinic()!=tot) cout<<"NO";
    else{
        cout<<"YES\n";
        for(int i=2;i<m*2+2;i+=2) cout<<l[i^1]+e[i^1].w<<"\n";
    }
}
有源汇有上下界最大流
ll n,m,x,y,wl,wr,ct=1,tot,S,T,SS,TT,h[N],a[N],now[N],d[N];
struct P{ll to,nxt,w;}e[M];
void add(ll x,ll y,ll w,bool p=1){e[++ct]={y,h[x],w},h[x]=ct;if(p) add(y,x,0,0);}
bool bfs(){
    memset(d,-1,sizeof d);
    queue<ll> q;q.push(S),d[S]=0,now[S]=h[S];
    while(!q.empty()){
        ll x=q.front();q.pop();
        for(int i=h[x];i;i=e[i].nxt)
            if(e[i].w&&!~d[e[i].to]){
                d[e[i].to]=d[x]+1,q.push(e[i].to),now[e[i].to]=h[e[i].to];
                if(e[i].to==T) return 1;
            }
    }
    return 0;
}
ll dfs(ll x,ll f,ll res=0){
    if(x==T) return f;
    for(int i=now[x];i&&f;i=e[i].nxt){
        now[x]=i;
        if(e[i].w&&d[e[i].to]==d[x]+1){
            ll t=dfs(e[i].to,min(f,e[i].w));
            if(t) e[i].w-=t,e[i^1].w+=t,res+=t,f-=t;
            else d[e[i].to]=-1;
        }
    }
    return res;
}
ll dinic(ll ct=0){while(bfs()) ct+=dfs(S,inf);return ct;}
void solve(){
	cin>>n>>m>>SS>>TT;S=n+2,T=n+3;
    for(int i=1;i<=m;i++) cin>>x>>y>>wl>>wr,add(x,y,wr-wl),a[x]-=wl,a[y]+=wl;
    for(int i=0;i<=n+1;i++)
        if(a[i]>0) add(S,i,a[i]),tot+=a[i];
        else add(i,T,-a[i]);
    add(TT,SS,inf);
    if(dinic()!=tot) cout<<"please go home to sleep";
    else{
        ll ans=e[ct].w;e[ct^1].w=e[ct].w=0;
        S=SS,T=TT;cout<<ans+dinic();
    }
}
有源汇有上下界最小流
ll n,m,x,y,wl,wr,ct=1,tot,S,T,SS,TT,h[N],a[N],now[N],d[N];
struct P{ll to,nxt,w;}e[M];
void add(ll x,ll y,ll w,bool p=1){e[++ct]={y,h[x],w},h[x]=ct;if(p) add(y,x,0,0);}
bool bfs(){
    memset(d,-1,sizeof d);
    queue<ll> q;q.push(S),d[S]=0,now[S]=h[S];
    while(!q.empty()){
        ll x=q.front();q.pop();
        for(int i=h[x];i;i=e[i].nxt)
            if(e[i].w&&!~d[e[i].to]){
                d[e[i].to]=d[x]+1,q.push(e[i].to),now[e[i].to]=h[e[i].to];
                if(e[i].to==T) return 1;
            }
    }
    return 0;
}
ll dfs(ll x,ll f,ll res=0){
    if(x==T) return f;
    for(int i=now[x];i&&f;i=e[i].nxt){
        now[x]=i;
        if(e[i].w&&d[e[i].to]==d[x]+1){
            ll t=dfs(e[i].to,min(f,e[i].w));
            if(t) e[i].w-=t,e[i^1].w+=t,res+=t,f-=t;
            else d[e[i].to]=-1;
        }
    }
    return res;
}
ll dinic(ll ct=0){while(bfs()) ct+=dfs(S,inf);return ct;}
void solve(){
	cin>>n>>m>>SS>>TT;S=n+2,T=n+3;
    for(int i=1;i<=m;i++) cin>>x>>y>>wl>>wr,add(x,y,wr-wl),a[x]-=wl,a[y]+=wl;
    for(int i=0;i<=n+1;i++)
        if(a[i]>0) add(S,i,a[i]),tot+=a[i];
        else add(i,T,-a[i]);
    add(TT,SS,inf);
    if(dinic()!=tot) cout<<"please go home to sleep";
    else{
        ll ans=e[ct].w;e[ct^1].w=e[ct].w=0;
        T=SS,S=TT;cout<<ans-dinic();
    }
}

其他

dijkstra
void dijkstra(ll s){
	priority_queue<pii,vector<pii>,greater<pii> > q;
	memset(dis,0x3f,sizeof dis);q.push({dis[s]=0,s});
	while(!q.empty()){
		ll x=q.top().se;q.pop();
		if(vis[x]) continue;vis[x]=1;
		for(auto p:e[x]){
			ll y=p.fi,w=p.se;
			if(dis[y]>dis[x]+w) q.push({dis[y]=dis[x]+w,y});
		}
	}
}
kruskal
struct P{ll x,y,w;bool operator<(const P& B){return w<B.w;}}e[N];
ll getfa(ll x){return fa[x]==x?x:fa[x]=getfa(fa[x]);}
bool hb(ll x,ll y){x=getfa(x),y=getfa(y);if(x!=y){fa[x]=y;return 1;}return 0;}
void kruskal(){
    for(int i=1;i<=n;i++) fa[i]=i;
    for(int i=1;i<=m;i++) if(hb(e[i].x,e[i].y)) ans+=e[i].w;
}
lca
void dfs(ll x,ll fa){
	d[x]=d[fa]+1,f[x][0]=fa;
	for(int i=1;i<=20;i++) f[x][i]=f[f[x][i-1]][i-1];
	for(auto y:e[x]) if(y!=fa) dfs(y,x);
}
ll lca(ll x,ll y){
	if(d[x]<d[y]) swap(x,y);
	for(int i=20;~i;i--) if(d[f[x][i]]>=d[y]) x=f[x][i];
	if(x==y) return x;
	for(int i=20;~i;i--) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
	return f[x][0];
}
lca(树剖版)
void dfs(ll x){
    sz[x]=1,d[x]=d[f[x]]+1;
    for(auto y:e[x]) if(y!=f[x]) f[y]=x,dfs(y),sz[x]+=sz[y];
}
void dfs1(ll x){
    ll t=0;
    if(!top[x]) top[x]=x;
    for(auto y:e[x]) if(y!=f[x]&&sz[y]>sz[t]) t=y;
    if(t) top[t]=top[x],dfs1(t);
    for(auto y:e[x]) if(y!=f[x]&&t!=y) dfs1(y);
}
ll lca(ll x,ll y){
    while(top[x]!=top[y]){
        if(d[top[x]]<d[top[y]]) x^=y^=x^=y;
        x=f[top[x]];
    }
    if(d[x]>d[y]) x^=y^=x^=y;
    return x;
}
树剖(树状数组)
void xg(ll s[],ll x,ll k){while(x<=n) s[x]+=k,s[x]%=p,x+=lowbit(x);}
void qxg(ll x,ll y,ll k){
	xg(s,x,k);xg(s,y+1,-k);
	xg(s2,x,x*k);xg(s2,y+1,-(y+1)*k);
}
ll sum(ll s[],ll x){
	ll ct=0;
	while(x) ct+=s[x],ct%=p,x-=lowbit(x);
	return ct;
}
ll query(ll l,ll r){return (((r+1)*sum(s,r)%p-sum(s2,r)-l*sum(s,l-1)%p+sum(s2,l-1))%p+p)%p;}
void add(ll x,ll y){e[x].pb(y),e[y].pb(x);}
void dfs(ll x,ll f){
	fa[x]=f,sz[x]=1,d[x]=d[f]+1;
	for(auto y:e[x]) if(y!=f) dfs(y,x),sz[x]+=sz[y],son[x]=(sz[y]>sz[son[x]]?y:son[x]);
}
void dfs2(ll x,ll f){
	top[x]=f,id[x]=++ct;
	if(w[x]) qxg(id[x],id[x],w[x]);
	if(!son[x]) return;
	dfs2(son[x],f);
	for(auto y:e[x]) if(y!=fa[x]&&y!=son[x]) dfs2(y,y);
}
void addp(ll x,ll y,ll k){
	k%=p;
	while(top[x]!=top[y]){
		if(d[top[x]]<d[top[y]]) x^=y^=x^=y;
		qxg(id[top[x]],id[x],k),x=fa[top[x]];
	}
	if(d[x]>d[y]) x^=y^=x^=y;
	qxg(id[x],id[y],k);
}
void adds(ll x,ll k){qxg(id[x],id[x]+sz[x]-1,k%p);}
ll queryp(ll x,ll y){
	ll res=0;
	while(top[x]!=top[y]){
		if(d[top[x]]<d[top[y]]) x^=y^=x^=y;
		res+=query(id[top[x]],id[x]),res%=p,x=fa[top[x]];
	}
	if(d[x]>d[y]) x^=y^=x^=y;
	res+=query(id[x],id[y]),res%=p;
	return res;
}
ll querys(ll x){return query(id[x],id[x]+sz[x]-1);}
长链剖分
void dfs(ll x,ll fa){
	d[x]=d[fa]+1;
	for(auto y:e[x]) if(y!=fa) dfs(y,x);
	rt=(d[rt]<d[x]?x:rt);
}
void dfs2(ll x,ll fa){
	for(auto y:e[x]) if(y!=fa) dfs2(y,x),son[x]=(f[son[x]]>f[y]?son[x]:y);
	f[x]=f[son[x]]+1;
	for(auto y:e[x]) if(y!=fa&&y!=son[x]) chain.pb(f[y]);
}
int main(){
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	cin>>n;
	for(int i=1;i<n;i++) cin>>x>>y,e[x].pb(y),e[y].pb(x);
	dfs(1,0);dfs2(rt,0),chain.pb(f[rt]);
	sort(chain.begin(),chain.end(),greater<ll>());	
	for(int i=2;i<=n&&i-2<chain.size();i++) ans[i]=ans[i-1]+chain[i-2];
	for(int i=chain.size()+2;i<=n;i++) ans[i]=ans[i-1];
	ans[1]=1;
	for(int i=1;i<=n;i++) cout<<ans[i]<<" ";
	return 0;
}
Prüfer 序列
void prufer(){
	ll x=0,leaf=0;
	for(int i=1;i<=n;i++) if(!d[i]){x=leaf=i;break;}
	for(int i=1;i<n-1;i++){
		p[i]=fa[leaf];
		if(!--d[fa[leaf]]&&fa[leaf]<x) leaf=fa[leaf];
		else{while(d[++x]);leaf=x;}
	}
}
void get_prufer(){
	ll x=0,leaf=0;while(d[++x]);leaf=x;
	for(int i=1;i<n-1;i++){
		fa[leaf]=p[i];
		if(!--d[fa[leaf]]&&fa[leaf]<x) leaf=fa[leaf];
		else{while(d[++x]);leaf=x;}
	}
	fa[leaf]=n;
}
点分治
void getrt(ll x,ll fa,ll n){
    sz[x]=1,mx[x]=0;
    for(auto p:e[x]) if(p.fi!=fa&&!vis[p.fi]) getrt(p.fi,x,n),mx[x]=max(mx[x],sz[p.fi]),sz[x]+=sz[p.fi];
    mx[x]=max(mx[x],n-sz[x]);
    if(!rt||mx[x]<mx[rt]) rt=x;
}
void init(ll x,ll fa){
    if(d[x]<M) t.pb(d[x]);
    for(auto p:e[x]) if(p.fi!=fa&&!vis[p.fi]) d[p.fi]=d[x]+p.se,init(p.fi,x);
}
void calc(ll x){
    all.clear();
    for(auto p:e[x])
        if(!vis[p.fi]){
            t.clear(),d[p.fi]=p.se,init(p.fi,x);            
            for(int i=1;i<=m;i++) if(!ans[i]) for(auto l:t) if(q[i]>=l&&ok[q[i]-l]){ans[i]=1;break;}
            for(auto l:t) ok[l]=1,all.pb(l);
        }
    for(auto l:all) ok[l]=0;
}
void solve(ll x){
    vis[x]=ok[0]=1;calc(x);
    for(auto p:e[x]) if(!vis[p.fi]) rt=0,getrt(p.fi,x,sz[p.fi]),solve(rt);
}
void treediv(){getrt(1,0,n);getrt(rt,0,n);solve(rt);}
LGV 引理
ll qp(ll a,ll b,ll ct=1){while(b){if(b&1) ct=ct*a%mod;a=a*a%mod,b>>=1;}return ct;}
ll C(ll n,ll m){return jc[n]*qp(jc[m],mod-2)%mod*qp(jc[n-m],mod-2)%mod;}
ll solve(ll n){
	ll res=1,kk=1;
	for(int i=1;i<=n;i++)
		for(int j=i+1;j<=n;j++){
			while(a[i][i]){
				ll t=a[j][i]/a[i][i];
				for(int k=i;k<=n;k++) ((a[j][k]-=a[i][k]*t)+=mod)%=mod;
				swap(a[i],a[j]),kk=-kk;
			}
			swap(a[i],a[j]),kk=-kk;
		}	
	for(int i=1;i<=n;i++) res*=a[i][i],res%=mod;
	res*=kk,res%=mod,res+=mod,res%=mod;
	return res;
}
void calc(){
	cin>>n>>m;
    for(int i=1;i<=m;i++) cin>>ta[i]>>tb[i];
    for(int i=1;i<=m;i++)
        for(int j=1;j<=m;j++)
            if(ta[i]<=tb[j]) a[i][j]=C(tb[j]-ta[i]+n-1,n-1);
            else a[i][j]=0;
    cout<<solve(m)<<"\n";
}

计算几何

极角排序
#define double long double
const ll N=1e5+10;
const double pi=acos(-1);
ll n,ans1,ans2;
double ans;
struct P{
	double x,y,a;ll i;
	bool operator<(const P& b){return a<b.a;}
}p[N];
void solve(){
	cin>>n;
	for(int i=1;i<=n;i++) cin>>p[i].x>>p[i].y,p[i].i=i,p[i].a=atan2(p[i].y,p[i].x),p[i].a+=(p[i].a<0?pi*2.:0.);
	sort(p+1,p+n+1);ans=p[1].a-p[n].a+pi*2.;ans1=p[1].i;ans2=p[n].i;
	for(int i=2;i<=n;i++) if(p[i].a-p[i-1].a<ans) ans=p[i].a-p[i-1].a,ans2=p[i].i,ans1=p[i-1].i;
	cout<<ans1<<" "<<ans2;
}
凸包
struct P{
    double x,y;
    bool operator<(const P& B)const{return x!=B.x?x<B.x:y<B.y;}
}a[N],s[N];
double K(P L,P R){return L.x!=R.x?(L.y-R.y)/(L.x-R.x):1e18;}
double dis(P L,P R){return sqrt((L.x-R.x)*(L.x-R.x)+(L.y-R.y)*(L.y-R.y));}
void solve(){
    top=0;
    for(int i=1;i<=n;i++){
        s[++top]=a[i];
        while(top>2&&K(s[top-2],s[top])<K(s[top-2],s[top-1])) s[top-1]=s[top],top--;
    }
    for(int i=1;i<top;i++) ans+=dis(s[i],s[i+1]);
}
void tubao(){
	sort(a+1,a+n+1);solve();
    reverse(a+1,a+n+1);solve();
}
半平面交
struct V{double x,y;}p[N],x[N];
struct P{V x,y;double an;}a[N],q[N];
P mk(V a,V b){return {a,b,atan2(b.y,b.x)};}
V operator +(V a,V b){return {a.x+b.x,a.y+b.y};}
V operator -(V a,V b){return {a.x-b.x,a.y-b.y};}
V operator *(V a,double b){return {a.x*b,a.y*b};}
V operator /(V a,double b){return {a.x/b,a.y/b};}
double dot(V a,V b){return a.x*b.x+a.y*b.y;}
double cross(V a,V b){return a.x*b.y-a.y*b.x;}
bool cmp(P a,P b){return a.an<b.an;}
bool check(P a,V b){return cross(a.y,b-a.x)<=-eps;}
V in(P a,P b){return a.x+a.y*(cross(b.y,a.x-b.x)/cross(a.y,b.y));}
bool half_plane(ll n){
	sort(a+1,a+n+1,cmp);
	q[0]=a[1];
	for(int i=2;i<=n;i++){
		while(l<r&&check(a[i],x[r])) r--;
		while(l<r&&check(a[i],x[l+1])) l++;
		q[++r]=a[i];
		if(fabs(cross(q[r].y,q[r-1].y))<=eps){
			if(check(q[r],q[r-1].x)&&dot(q[r].y,q[r-1].y)<=-eps) return 0;
			r--;
			if(!check(q[r],a[i].x)) q[r]=a[i];
		}
		if(l<r) x[r]=in(q[r],q[r-1]);
	}
	while(l<r&&check(q[l],x[r])) r--;
	if(r-l<=1) return 0;
	x[l]=in(q[l],q[r]);
	return 1;
}
double polygonsize(ll n,V *a){
	double res=0;
	for(int i=1;i<n;i++) res+=cross(a[i],a[i+1]);
	res+=cross(a[n],a[1]);
	return res/2;
}
void solve(){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>m;
		for(int j=1;j<=m;j++) cin>>p[j].x>>p[j].y;
		for(int j=1;j<m;j++) a[++ct]=mk(p[j],p[j+1]-p[j]);
		a[++ct]=mk(p[m],p[1]-p[m]);
	}
	if(!half_plane(ct)) cout<<"0.000";
	else cout<<fixed<<setprecision(3)<<polygonsize(r-l+1,x+l-1);
}

字符串

kmp
void init(){
	for(int i=2,j=0;i<=m;i++){
		while(j&&b[i]!=b[j+1]) j=nxt[j];
		nxt[i]=(j+=(b[i]==b[j+1]));
	}
}
void kmp(){
	for(int i=1,j=0;i<=n;i++){
		while(j&&a[i]!=b[j+1]) j=nxt[j];
		if(a[i]==b[j+1]) j++;
		if(j==m) cout<<i-m+1<<"\n",j=nxt[j];
	}
}
exkmp
void Z(){
	z[1]=m;
	for(ll i=2,l=0,r=0;i<=m;i++){
		if(i<=r) z[i]=min(z[i-l+1],r-i+1);
		while(i+z[i]<=m&&t[i+z[i]]==t[1+z[i]]) z[i]++;
		if(i+z[i]-1>r) l=i,r=i+z[i]-1; 
	}
}
void exkmp(){
	Z();
	for(ll i=1,l=0,r=0;i<=n;i++){
		if(i<=r) p[i]=min(z[i-l+1],r-i+1);
		while(i+p[i]<=n&&s[i+p[i]]==t[1+p[i]]) p[i]++;
		if(i+p[i]-1>r) l=i,r=i+p[i]-1; 
	}
}
AC 自动机
ll n,ct,x,t[N][33],ed[N],fail[N],ans[N];
string s;vector<ll> e[N];
ll insert(string s,ll x=0){
    for(auto c:s){
        if(!t[x][c-'a']) t[x][c-'a']=++ct;
        x=t[x][c-'a'];
    }
    return x;
}
void bfs(){
    queue<ll> q;
    for(int i=0;i<26;i++)
        if(t[0][i]) q.push(t[0][i]);
    while(q.size()){
        ll x=q.front();q.pop();
        for(int i=0;i<26;i++)
            if(!t[x][i]) t[x][i]=t[fail[x]][i];
            else fail[t[x][i]]=t[fail[x]][i],q.push(t[x][i]);
    }
}
最小表示法
j=1;
for(;i<n&&j<n&&k<n;)
	if(a[(i+k)%n]==a[(j+k)%n]) k++;
	else if(a[(i+k)%n]>a[(j+k)%n]) i+=k+1,i+=(i==j),k=0;
	else j+=k+1,i+=(i==j),k=0;
ans=min(i,j);
SA
void SA(){
    for(int i=1;i<=n;i++) rk[i]=s[i],c[s[i]]++;
    for(int i=2;i<=m;i++) c[i]+=c[i-1];
    for(int i=n;i;i--) sa[c[rk[i]]--]=i;
    for(ll k=1;k<=n;k<<=1){
        pos=0;for(int i=1;i<=m;i++) c[i]=0;
        for(int i=n-k+1;i<=n;i++) rk2[++pos]=i;
        for(int i=1;i<=n;i++) if(sa[i]>k) rk2[++pos]=sa[i]-k;
        for(int i=1;i<=n;i++) c[rk[i]]++;
        for(int i=2;i<=m;i++) c[i]+=c[i-1];
        for(int i=n;i;i--) sa[c[rk[rk2[i]]]--]=rk2[i],rk2[i]=0;
        swap(rk,rk2);pos=1;rk[sa[1]]=1;
        for(int i=2;i<=n;i++)
            rk[sa[i]]=(pos+=(rk2[sa[i-1]]!=rk2[sa[i]]||rk2[sa[i-1]+k]!=rk2[sa[i]+k]));
        if(pos==n) return;m=pos;
    }
}
sam
int ct=1,lst=1,sum[N];ll ans;string s;
vector<int> e[N];
struct SAM{int fa=0,len=0,ch[26]={};}t[N];
void insert(int x){
    int p=lst,np=lst=++ct;t[np].len=t[p].len+1;sum[ct]=1;
    while(!t[p].ch[x]) t[p].ch[x]=np,p=t[p].fa;
    if(!p) t[np].fa=1;
    else{
        int q=t[p].ch[x];
        if(t[q].len==t[p].len+1) t[np].fa=q;
        else{
            int nq=++ct;t[nq]=t[q];t[nq].len=t[p].len+1,t[q].fa=t[np].fa=nq;
            while(t[p].ch[x]==q) t[p].ch[x]=nq,p=t[p].fa;
        }
    }
}
void dfs(int x){
    for(auto y:e[x]) dfs(y),sum[x]+=sum[y];
    if(sum[x]!=1) ans=max(ans,1ll*sum[x]*t[x].len);
}

卡常

快读快写
int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    return x*f;
}
void write(int x){
    if(x<0) putchar('-'),x=-x;
	if(x>9) write(x/10);
	putchar(x%10+'0');
}
火车头
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC target("avx")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
posted @ 2025-03-04 10:19  见合  阅读(88)  评论(0)    收藏  举报
Live2D + Music