模板

数学

组合数学

快速取模
#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;
}
组合数
void init(){jc[0]=1;for(int i=1;i<N;i++) jc[i]=jc[i-1]*i%mod;} 
ll ksm(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]*ksm(jc[n-m],mod-2)%mod*ksm(jc[m],mod-2)%mod;}
组合数 O(m)
ll ksm(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*ksm(t,mod-2)%mod;
}
组合数(卡常)
ll ksm(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]=ksm(jc[n],mod-2);
	for(int i=N-11;~i;i--) inv[i]=inv[i+1]*(i+1)%mod;
}
逆元
for(ll i=2;i<=n;i++) dp[i]=(p-p/i)*dp[p%i]%p;
ksm+exgcd+BSGS
map<ll,ll> mp;
ll ksm(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=ksm(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);}

线性代数

矩阵快速幂
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 ksm(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){ksm(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=ksm(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;}

数据结构

线段树家族

线段树 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
void up(ll rt){t[rt]=(t[rt<<1]+t[rt<<1|1])%mod;}
void build(ll rt,ll l,ll r){
	lazy2[rt]=1;
	if(l==r){t[rt]=a[l];return;}
	ll mid=l+r>>1;
	build(rt<<1,l,mid),build(rt<<1|1,mid+1,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 mid,ll r){
	down(rt<<1,l,mid,lazy[rt],lazy2[rt]);
	down(rt<<1|1,mid+1,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;}
	ll mid=l+r>>1;push_down(rt,l,mid,r);
	update(rt<<1,l,mid,rl,rr,k),update(rt<<1|1,mid+1,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;}
	ll mid=l+r>>1;push_down(rt,l,mid,r);
	update2(rt<<1,l,mid,rl,rr,k),update2(rt<<1|1,mid+1,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];
	ll mid=l+r>>1;push_down(rt,l,mid,r);
	return (query(rt<<1,l,mid,rl,rr)+query(rt<<1|1,mid+1,r,rl,rr))%mod;
}
动态开点线段树
struct Tree{ll ls,rs,val,lazy=-1;}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){t[rt].lazy=k,t[rt].val=(r-l+1)*k;}
void push_down(ll rt,ll l,ll mid,ll r){
	if(!~t[rt].lazy) return;
	down(t[rt].ls,l,mid,t[rt].lazy);
	down(t[rt].rs,mid+1,r,t[rt].lazy);
	t[rt].lazy=-1;
}
void update(ll rt,ll l,ll r,ll rl,ll rr,ll k){
	if(rr<l||r<rl) 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;
	ll mid=l+r>>1;push_down(rt,l,mid,r);
	update(t[rt].ls,l,mid,rl,rr,k);update(t[rt].rs,mid+1,r,rl,rr,k);
	up(rt);
}
线段树-区间加 区间求 gcd
void up(ll rt){t[rt]=__gcd(t[rt<<1],t[rt<<1|1]),s[rt]=s[rt<<1]+s[rt<<1|1];}
void build(ll rt,ll l,ll r){
    if(l==r){t[rt]=s[rt]=a[l]-a[l-1];return;}
    ll mid=l+r>>1;
    build(rt<<1,l,mid),build(rt<<1|1,mid+1,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;}
    ll mid=l+r>>1;
    update(rt<<1,l,mid,x,d),update(rt<<1|1,mid+1,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];
    ll mid=l+r>>1;
    return __gcd(query(rt<<1,l,mid,rl,rr),query(rt<<1|1,mid+1,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];
    ll mid=l+r>>1;
    return sum(rt<<1,l,mid,rl,rr)+sum(rt<<1|1,mid+1,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)));}
线段树-区间赋值 区间覆盖 区间求和
void up(ll rt){t[rt]=t[rt<<1]+t[rt<<1|1];}
void push_down(ll rt,ll l,ll mid,ll r){
	if(~lazy2[rt]){
        t[rt<<1]=lazy2[rt]*(mid-l+1);
        t[rt<<1|1]=lazy2[rt]*(r-mid);
		lazy2[rt<<1]=lazy2[rt<<1|1]=lazy2[rt];
		lazy[rt<<1]=lazy[rt<<1|1]=0;
		lazy2[rt]=-1;
	}
	if(lazy[rt]){
		lazy[rt<<1]^=1;
		lazy[rt<<1|1]^=1;
        t[rt<<1]=mid-l+1-t[rt<<1];
        t[rt<<1|1]=r-mid-t[rt<<1|1];
		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;}
	ll mid=l+r>>1;push_down(rt,l,mid,r);
	update(rt<<1,l,mid,rl,rr),update(rt<<1|1,mid+1,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;}
	ll mid=l+r>>1;push_down(rt,l,mid,r);
	cover(rt<<1,l,mid,rl,rr,k),cover(rt<<1|1,mid+1,r,rl,rr,k);
    up(rt);
}
ll query(ll rt,ll l,ll r){
	if(l==r) return l;
	ll mid=l+r>>1;push_down(rt,l,mid,r);
	if(t[rt<<1]<mid-l+1) return query(rt<<1,l,mid);
    return query(rt<<1|1,mid+1,r);
}
void init(){memset(lazy2,-1,sizeof lazy2);}
线段树分治
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;}
    ll mid=l+r>>1;
    update(rt<<1,l,mid,rl,rr,k),update(rt<<1|1,mid+1,r,rl,rr,k);
}
void dfs(ll rt,ll l,ll r){
    bool flag=1;ll mid=l+r>>1,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(rt<<1,l,mid),dfs(rt<<1|1,mid+1,r);
    }
    while(s.size()>lst) sz[fa[s.top().fi]]-=s.top().se,fa[s.top().fi]=s.top().fi,s.pop();
}
线段树优化建图
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;}
	ll mid=l+r>>1;
	Add(rt,rt<<1),Add(rt,rt<<1|1);
	Add((rt<<1)+P,rt+P),Add((rt<<1|1)+P,rt+P);
	build(rt<<1,l,mid),build(rt<<1|1,mid+1,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;
	}	
	ll mid=l+r>>1;
	add(rt<<1,l,mid,rl,rr,v,w,op),add(rt<<1|1,mid+1,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});
		}
	}
}
int main(){
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	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]])<<" ";
	return 0;
}
扫描线
#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);}
平衡树(数组版)
ll New(ll x){val[++ct]=x,da[ct]=rand(),sz[ct]=cnt[ct]=1;return ct;}
void up(ll rt){sz[rt]=sz[son[rt][0]]+sz[son[rt][1]]+cnt[rt];}
void build(){root=New(-inf),son[root][1]=New(inf),up(root);}
void ro(ll &rt,bool d){// rotate
	ll t=son[rt][!d];son[rt][!d]=son[t][d],son[t][d]=rt,rt=t;
	up(son[rt][d]),up(rt);
}
void in(ll &rt,ll x){// insert
	if(!rt){rt=New(x);return;}
	if(val[rt]==x){cnt[rt]++,up(rt);return;}
	bool d=(x>val[rt]);in(son[rt][d],x);
	if(da[rt]<da[son[rt][d]]) ro(rt,!d);
	up(rt);
}
void de(ll &rt,ll x){// delete
	if(!rt) return;
	if(val[rt]==x){
		if(cnt[rt]>1){cnt[rt]--;up(rt);return;}
		if(son[rt][0]||son[rt][1]){
			if(!son[rt][1]||da[son[rt][0]]>da[son[rt][1]]) ro(rt,1),de(son[rt][1],x);
			else ro(rt,0),de(son[rt][0],x);
			up(rt);
		}else rt=0;
		return;
	}
	if(x<val[rt]) de(son[rt][0],x);
	else de(son[rt][1],x);
	up(rt);
}
ll ra(ll rt,ll x){// rank
	if(!rt) return 1;
	if(val[rt]==x) return sz[son[rt][0]]+1;
	if(val[rt]>x) return ra(son[rt][0],x);
	return sz[son[rt][0]]+cnt[rt]+ra(son[rt][1],x);
}
ll se(ll rt,ll x){// search
	if(!rt) return inf;
	if(x<=sz[son[rt][0]]) return se(son[rt][0],x);
	if(x<=sz[son[rt][0]]+cnt[rt]) return val[rt];
	return se(son[rt][1],x-sz[son[rt][0]]-cnt[rt]);
}
ll pr(ll x){// pre
	ll rt=root,p=0;
	while(rt)
		if(val[rt]<x) p=val[rt],rt=son[rt][1];
		else rt=son[rt][0];
	return p;
}
ll ne(ll x){// next
	ll rt=root,p=0;
	while(rt)
		if(val[rt]>x) p=val[rt],rt=son[rt][0];
		else rt=son[rt][1];
	return p;
}
平衡树(结构体版)
#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;
}
主席树
#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)];}

暴力数据结构

带修莫队
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--);
}

其他

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;
	}
}

图论/树论

tarjan 系列

缩点
void tarjan(ll x){
	dfn[x]=low[x]=++ct,s[++top]=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+1]!=x) belong[s[top]]=tot,vis[s[top--]]=0;
	}
}
割点
void tarjan(ll x,ll fa,ll rt){
	dfn[x]=low[x]=++ct;ll s=0;
	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){
	low[x]=dfn[x]=++ct;
	ll son=0;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){
	s[++top]=x,dfn[x]=low[x]=(++ct);
	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--]);
	}
}

其他

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);}

计算几何

极角排序
#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();
}

字符串

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];
	}
}

网络流

网络最大流
void add(ll u,ll v,ll w){e[++ct]={v,h[u],w},h[u]=ct;}
bool bfs(){
	for(int i=1;i<=n;i++) dis[i]=inf;
	queue<ll> q;
	q.push(s);dis[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>0&&dis[e[i].to]==inf){
				q.push(e[i].to);dis[e[i].to]=dis[x]+1,now[e[i].to]=h[e[i].to];
				if(e[i].to==t) return 1;
			}
	}
	return 0;
}
ll dfs(ll x,ll v){
	if(x==t) return v;
	ll res=0,k=0;
	for(int i=now[x];i&&v;i=e[i].nxt){
		now[x]=i;
		if(e[i].w>0&&dis[e[i].to]==dis[x]+1){
			k=dfs(e[i].to,min(v,e[i].w));
			if(!k) dis[e[i].to]=inf;
			e[i].w-=k,e[i^1].w+=k;
			res+=k,v-=k;
		}
	}
	return res;
}
ll Dinic(){
    ll ans=0;
    while(bfs()) ans+=dfs(s,inf);
	return ans;
}

卡常

快读快写
int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(c=='-') 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 @ 2024-05-20 21:33  见合  阅读(65)  评论(0编辑  收藏  举报