板子库

CSP-S 2023 试机

  1. 线段树pushdown l,r写反了
  2. 线段树query t[k].l写成l,r也是
  3. ST表query
st[r-(1<<s)+1][s]
  1. 线性阶乘逆元
inv[i]=inv[i+1] * (i+1) % mod

NOIP2023 试机

  1. 线段树 k<<1 写成 k>>1
  2. 线段树query t[k].l 写成l,r也是
  3. ST表查询 ans=max(st[l][s],st[r-(1<<s)+1][s])
  4. 线性筛 if(i%prime[j]==0) break; 写成 if(i%prime[j]) break;

CSP2024 试机

完美

常用杂项

对拍

#include<bits/stdc++.h>
using namespace std;
int main(){
	for(int i=1;i<=1e9;i++){
		system("makedata.exe");
		system("a.exe");
		system("b.exe");
		if(system("fc a.out b.out")) break;
		printf("AC #%d\n",i);
	}
	return 0;
}

缺省源

#include<bits/stdc++.h>
#define MAXN 100005
#define mod 998244353
#define look_memory cerr<<abs(&M2-&M1)/1024.0/1024<<'\n'
#define look_time cerr<<(clock()-Time)*1.0/CLOCKS_PER_SEC<<'\n'
using namespace std;

inline int read(){
    int x=0,f=1;
    char c=getchar();
    while(c<'0' || c>'9'){
        if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0' && c<='9'){
        x=(x<<1)+(x<<3)+(c^48);
        c=getchar();
    }
    return x*f;
}

bool M1;

bool M2;

signed main(){
//  freopen("","r",stdin);
//  freopen("","w",stdout);
    int Time=clock();

    look_memory;
    look_time;
    return 0;
}

卡时

if((double)clock()/CLOCKS_PER_SEC > 0.98) break;

函数

  • popcnt:__builtin_popcount(sta)

  • 归并排序:inplace_merge(a+l,a+mid+1,a+r+1,cmp)

  • 线性中位数:nth_element(a+l,a+mid,a+r+1,cmp)

  • 全排列:next_permutation(a+1,a+1+n)

数据结构

线段树

/*
基础线段树 区间加区间求和 带lazytag
*/
#include<bits/stdc++.h>
#define MAXN 100005
using namespace std;

inline int read(){
	int x=0;
	char c=getchar();
	while(c<'0' || c>'9'){
		c=getchar();
	}
	while(c>='0' && c<='9'){
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return x;
}

int n,m;
long long a[MAXN];
struct node{
	int l,r;
	long long val,tag;
}t[MAXN<<2];

void pushup(int k){
	t[k].val=t[k<<1].val+t[k<<1|1].val;
}

void pushdown(int k){
	if(t[k].tag!=0){
		t[k<<1].val+=(t[k<<1].r-t[k<<1].l+1)*t[k].tag;
		t[k<<1].tag+=t[k].tag;
		t[k<<1|1].val+=(t[k<<1|1].r-t[k<<1|1].l+1)*t[k].tag;
		t[k<<1|1].tag+=t[k].tag;
		t[k].tag=0;
	}
}

void build(int k,int l,int r){
	t[k].l=l;t[k].r=r;
	if(l==r){
		t[k].val=a[l];
		return;
	}
	int mid=(l+r)>>1;
	build(k<<1,l,mid);
	build(k<<1|1,mid+1,r);
	pushup(k);
	return;
}

void update(int k,int l,int r,int v){
	if(t[k].l>=l && t[k].r<=r){
		t[k].val+=(t[k].r-t[k].l+1)*v;
		t[k].tag+=v;
		return;
	}
	pushdown(k);
	int mid=(t[k].l+t[k].r)>>1;
	if(mid>=l){
		update(k<<1,l,r,v);
	}
	if(mid<r){
		update(k<<1|1,l,r,v);
	}
	pushup(k);
}

long long query(int k,int l,int r){
	if(t[k].l>=l && t[k].r<=r){
		return t[k].val;
	}
	long long res=0;
	pushdown(k);
	int mid=(t[k].l+t[k].r)>>1;
	if(mid>=l){
		res+=query(k<<1,l,r);
	}
	if(mid<r){
		res+=query(k<<1|1,l,r);
	}
	return res;
}

int main(){
	//freopen("","r",stdin);
	//freopen("","w",stdout);
	n=read();m=read();
	for(int i=1;i<=n;i++){
		a[i]=read();
	}
	build(1,1,n);
	int op,l,r,v;
	while(m--){
		op=read();
		l=read();r=read();
		if(op==1){
			v=read();
			update(1,l,r,v);
		}else{
			long long ans=query(1,l,r);
			printf("%lld\n",ans);
		}
	}
	return 0;
}

树状数组

#include<bits/stdc++.h>
#define MAXN 500005
using namespace std;

inline int read(){
	int x=0;
	int f=1;
	char c=getchar();
	while(c<'0' || c>'9'){
		if(c=='-') f=-1;
		c=getchar();
	}
	while(c>='0' && c<='9'){
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return x*f;
}

int n,m;
int a[MAXN],c[MAXN];

int lowbit(int x){
	return x&(-x);
}

void update(int x,int v){
	while(x<=n){
		c[x]+=v;
		x+=lowbit(x);
	}
}

int query(int x){
	int res=0;
	while(x){
		res+=c[x];
		x-=lowbit(x);
	}
	return res;
}

int main(){
	n=read();m=read();
	for(int i=1;i<=n;i++){
		a[i]=read();
		update(i,a[i]);
	}
	int op,x,y;
	while(m--){
		op=read();
		x=read();y=read();
		if(op==1){
			update(x,y);
		}else{
			int ans=query(y)-query(x-1);
			printf("%d\n",ans);
		}
	}
	return 0;
}
#include<bits/stdc++.h>
#define MAXN 500005
using namespace std;

inline int read(){
	int x=0;
	int f=1;
	char c=getchar();
	while(c<'0' || c>'9'){
		if(c=='-') f=-1;
		c=getchar();
	}
	while(c>='0' && c<='9'){
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return x*f;
}

int n,m;
int a[MAXN],c[MAXN];

int lowbit(int x){
	return x&(-x);
}

void update(int x,int v){
	while(x<=n){
		c[x]+=v;
		x+=lowbit(x);
	}
}

int query(int x){
	int res=0;
	while(x){
		res+=c[x];
		x-=lowbit(x);
	}
	return res;
}

int main(){
	n=read();m=read();
	for(int i=1;i<=n;i++){
		a[i]=read();
		update(i,a[i]-a[i-1]);
	}
	int op,x,y,v;
	while(m--){
		op=read();
		x=read();
		if(op==1){
			y=read();
			v=read();
			update(x,v);
			update(y+1,-v);
		}else{
			int ans=query(x);
			printf("%d\n",ans);
		}
	}
	return 0;
}

ST表

#include<bits/stdc++.h>
#define MAXN 100005
using namespace std;

inline int read(){
	int x=0;
	char c=getchar();
	while(c<'0' || c>'9'){
		c=getchar();
	}
	while(c>='0' && c<='9'){
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return x;
}

int n,m;
int st[MAXN][20];
int lg[MAXN],logn;

void init(){
	lg[1]=0;
	lg[2]=1;
	for(int i=3;i<=n;i++){
		lg[i]=lg[i>>1]+1;
	}
	logn=lg[n];
	for(int j=1;j<=logn;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]);
		}
	}
}

int main(){
	//freopen("","r",stdin);
	//freopen("","w",stdout);
	n=read();m=read();
	for(int i=1;i<=n;i++){
		st[i][0]=read();
	}
	init();
	int l,r;
	while(m--){
		l=read();r=read();
		int s=lg[r-l+1];
		int ans=max(st[l][s],st[r-(1<<s)+1][s]);
		printf("%d\n",ans);
	}
	return 0;
}

并查集 影子并查集

#include<bits/stdc++.h>
#define MAXN 50005
using namespace std;

inline int read(){
	int x=0;
	char c=getchar();
	while(c<'0' || c>'9'){
		c=getchar();
	}
	while(c>='0' && c<='9'){
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return x;
}

int n,m;
int fa[MAXN],val[MAXN];
int ans;

int find(int x){
	if(x==fa[x]) return fa[x];
	int f=fa[x];
	fa[x]=find(fa[x]);
	val[x]=(val[x]+val[f])%3;
	return fa[x];
}

void merge(int x,int y){
	x=find(x);
	y=find(y);
	fa[y]=x;
	val[x]+=val[y];
}

int main(){
	//freopen("","r",stdin);
	//freopen("","w",stdout);
	n=read();m=read();
	for(int i=1;i<=n;i++){
		fa[i]=i;
	}
	int op,x,y;
	while(m--){
		op=read();
		x=read();y=read();
		if(x>n || y>n || (op==2 && x==y)){
			ans++;
			continue;
		}
		int fx=find(x);
		int fy=find(y);
		if(op==1){
			if(fx==fy){
				if(val[x]!=val[y]) ans++;
			}else{
				fa[fx]=fy;
				val[fx]=(val[y]-val[x]+3)%3;
			}
		}else{
			if(fx==fy){
				int tmp=(val[x]-val[y]+3)%3;
				if(tmp!=1) ans++;
			}else{
				fa[fx]=fy;
				val[fx]=(val[y]-val[x]+1+3)%3;
			}
		}
	}
	printf("%d",ans);
	return 0;
}

//小根堆
priority_queue <int,vector<int>,greater<int>> q1;
//大根堆
priority_queue <int,vector<int>,less<int>> q2;
//默认大根堆
priority_queue<int> q;
struct node{
	int x;
	bool operator < (node tmp) const{
		return tmp.x<x;
	}
};//tmp是this 这个是小根堆
priority_queue<node> myq;

左偏树(可并堆)

#include<bits/stdc++.h>
#define MAXN 100005
using namespace std;

inline int read(){
	int x=0;
	int f=1;
	char c=getchar();
	while(c<'0' || c>'9'){
		if(c=='-') f=-1;
		c=getchar();
	}
	while(c>='0' && c<='9'){
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return x*f;
}

int n,m;
struct node{
	int ls,rs;
	int id,dis,val;
	bool operator < (node x) const{
		return val==x.val ? id<x.id : val<x.val;
	}
}t[MAXN];
int fa[MAXN];
bool mark[MAXN];

int find(int x){
	if(x==fa[x]) return fa[x];
	return fa[x]=find(fa[x]);
	
}

int merge(int x,int y){
	if(x*y==0) return x+y;
	if(t[y]<t[x]) swap(x,y);
	t[x].rs=merge(t[x].rs,y);
	fa[t[x].rs]=x;
	if(t[t[x].ls].dis<t[t[x].rs].dis) swap(t[x].ls,t[x].rs);
	t[x].dis=t[t[x].rs].dis+1;
	return x;
}

void pop(int x){
	fa[t[x].ls]=fa[t[x].rs]=fa[x]=merge(t[x].ls,t[x].rs);
	t[x].ls=t[x].rs=t[x].dis=0;
}


int main(){
	n=read();m=read();
	for(int i=1;i<=n;i++){
		t[i].val=read();
		t[i].id=i;
		fa[i]=i;
	}
	int op,x,y;
	while(m--){
		op=read();
		if(op==1){
			x=read();y=read();
			if(mark[x] || mark[y]) continue;
			x=find(x);y=find(y);
			if(x!=y) fa[x]=fa[y]=merge(x,y);
		}else{
			x=read();
			if(mark[x]){
				puts("-1");
				continue;
			}
			x=find(x);
			printf("%d\n",t[x].val);
			mark[x]=true;
			pop(x);
		}
	}
	return 0;
}

分块

李超线段树

#include<bits/stdc++.h>
#define MAXN 100005
#define mod 998244353
#define ls k<<1
#define rs k<<1|1
#define look_memory cerr<<abs(&M2-&M1)/1024.0/1024<<'\n'
#define look_time cerr<<(clock()-Time)*1.0/CLOCKS_PER_SEC<<'\n'
using namespace std;

inline int read(){
    int x=0;
    int f=1;
    char c=getchar();
    while(c<'0' || c>'9'){
    	if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0' && c<='9'){
        x=(x<<1)+(x<<3)+(c^48);
        c=getchar();
    }
    return x*f;
}

bool M1;
int n;
struct line{
	double k,b;
}lin[MAXN];
int tot;
int t[MAXN<<2];
const int N=50000;
const double inf=1e9;

double get_val(int i,int x){
	return lin[i].k*x+lin[i].b;
}

void update(int k,int l,int r,int x){
	if(l==r){
		if(get_val(x,l)>get_val(t[k],l)) t[k]=x;
		return;
	}
	int mid=(l+r)>>1;
	if(get_val(x,mid)>get_val(t[k],mid)) swap(t[k],x);
	if(get_val(x,l)>get_val(t[k],l)) update(ls,l,mid,x);
	if(get_val(x,r)>get_val(t[k],r)) update(rs,mid+1,r,x);
}

double query(int k,int l,int r,int x){
	if(l==r) return get_val(t[k],x);
	int mid=(l+r)>>1;
	if(mid>=x) return max(get_val(t[k],x),query(ls,l,mid,x));
	else return max(get_val(t[k],x),query(rs,mid+1,r,x));
}

bool M2;

signed main(){
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	int Time=clock();
	n=read();
	char op[10];
	double k,b;
	int x;
	while(n--){
		scanf("%s",op);
		if(op[0]=='P'){
			scanf("%lf %lf",&b,&k);
			lin[++tot]=(line){k,b-k};
			update(1,1,N,tot);
		}else{
			x=read();
			int ans=query(1,1,N,x);
			printf("%d\n",ans/100);
		}
	}
	look_memory;
	look_time;
	return 0;
}

平衡树

权值Treap

#include<bits/stdc++.h>
#define MAXN 100005
using namespace std;

inline long long read(){
	long long x=0;
	int f=1; 
	char c=getchar();
	while(c<'0' || c>'9'){
		if(c=='-') f=-1;
		c=getchar();
	}
	while(c>='0' && c<='9'){
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return x*f;
}

int n,tot;
struct node{
	int val,key;//权值,堆值 
	int ls,rs;//左右儿子编号
	int sz;//大小,该元素数量 
}t[MAXN];

int rt,x,y;

int get_new(int x){
	tot++;
	t[tot].val=x;
	t[tot].key=rand();
	t[tot].sz=1;
	return tot;
}

void pushup(int k){
	t[k].sz=t[t[k].ls].sz+t[t[k].rs].sz+1;
}

void split(int k,int &x,int &y,int ky){//分裂 将k中<=ky的分到x >ky的分到y 
	if(k==0){
		x=y=0;
		return;
	}
	if(t[k].val<=ky){
		x=k;
		split(t[k].rs,t[x].rs,y,ky);
	}else{
		y=k;
		split(t[k].ls,x,t[y].ls,ky);
	}
	pushup(k);
}

void merge(int &k,int x,int y){//合并 将x和y合并为k 
	if(x*y==0){
		k=x+y;
		return;
	}
	if(t[x].key>t[y].key){
		k=x;
		merge(t[k].rs,t[x].rs,y);
	}else{
		k=y;
		merge(t[k].ls,x,t[y].ls);
	}
	pushup(k);
}

int find(int num){
	int now=rt;
	while(true){
		if(t[t[now].ls].sz==num-1){
			return t[now].val;
		}else if(t[t[now].ls].sz<num-1){
			num-=t[t[now].ls].sz+1;
			now=t[now].rs;
		}else{
			now=t[now].ls;
		}		
	}
	return 0;
}

int main(){
	srand(time(0));
	n=read();
	int op,v;
	while(n--){
		op=read();
		v=read();
		if(op==1){
			int nw=get_new(v);
			split(rt,rt,x,v);
			merge(rt,rt,nw);
			merge(rt,rt,x);
		}else if(op==2){
			split(rt,rt,y,v);
			split(rt,rt,x,v-1);
			merge(x,t[x].ls,t[x].rs);
			merge(rt,rt,x);
			merge(rt,rt,y);			
		}else if(op==3){
			split(rt,rt,x,v-1);
			printf("%d\n",t[rt].sz+1);
			merge(rt,rt,x);
		}else if(op==4){
			printf("%d\n",find(v));
		}else if(op==5){
			split(rt,rt,x,v-1);
			int now=rt;
			while(t[now].rs) now=t[now].rs;
			printf("%d\n",t[now].val);
			merge(rt,rt,x);
		}else if(op==6){
			split(rt,rt,x,v);
			int now=x;
			while(t[now].ls) now=t[now].ls;
			printf("%d\n",t[now].val);
			merge(rt,rt,x);			
		}
	}
	return 0;
}

序列Treap

#include<bits/stdc++.h>
#define MAXN 100005
using namespace std;

inline long long read(){
	long long x=0;
	int f=1;
	char c=getchar();
	while(c<'0' || c>'9'){
		if(c=='-') f=-1;
		c=getchar();
	}
	while(c>='0' && c<='9'){
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return x*f;
}

int n,m;
int a[MAXN];
struct node{
	int val,key;//权值,堆值 
	int ls,rs;//左右儿子编号
	int sz;
	int ec;//exchange
}t[MAXN];
int rt,x,y;

void make_exchange(int k){
	t[k].ec^=1;
	swap(t[k].ls,t[k].rs);
}

void pushup(int k){
	t[k].sz=t[t[k].ls].sz+t[t[k].rs].sz+1;
}

void pushdown(int k){
	if(t[k].ec){
		make_exchange(t[k].ls);
		make_exchange(t[k].rs);
		t[k].ec=0;
	}
}

void split(int k,int &x,int &y,int ky){
	if(k==0){
		x=y=0;
		return;
	}
	pushdown(k);
	if(t[t[k].ls].sz+1<=ky){
		x=k;
		split(t[k].rs,t[x].rs,y,ky-t[t[k].ls].sz-1);
	}else{
		y=k;
		split(t[k].ls,x,t[y].ls,ky);
	}
	pushup(k);
}

void merge(int &k,int x,int y){
	if(x*y==0){
		k=x+y;
		return;
	}
	if(t[x].key>t[y].key){
		k=x;
		pushdown(k);
		merge(t[k].rs,t[x].rs,y);
	}else{
		k=y;
		pushdown(k);
		merge(t[k].ls,x,t[y].ls);
	}
	pushup(k);
}

void dfs(int k){
	if(k==0) return;
	pushdown(k);
	dfs(t[k].ls);
	printf("%d ",t[k].val);
	dfs(t[k].rs);
}

int main(){
	srand(time(0));
	n=read();m=read();
	for(int i=1;i<=n;i++){
		t[i].val=i;
		t[i].sz=1;
		t[i].key=rand();
		merge(rt,rt,i);
	}
	int l,r;
	while(m--){
		l=read();r=read();
		split(rt,rt,y,r);
		split(rt,rt,x,l-1);
		make_exchange(x);
		merge(rt,rt,x);
		merge(rt,rt,y);
	}
	dfs(rt);
	return 0;
}

权值Splay

#include<bits/stdc++.h>
#define MAXN 100005
using namespace std;

inline long long read(){
	long long x=0;
	int f=1;
	char c=getchar();
	while(c<'0' || c>'9'){
		if(c=='-') f=-1;
		c=getchar();
	}
	while(c>='0' && c<='9'){
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return x*f;
}

int n;
int ch[MAXN][5],fa[MAXN],val[MAXN],cnt[MAXN],sz[MAXN];
//0表示左儿子 1表示右儿子 
int rt,tot;
const int inf=0x7fffffff;

int get_new(int v){
	tot++;
	fa[tot]=ch[tot][0]=ch[tot][1]=0;
	val[tot]=v;
	cnt[tot]=sz[tot]=1;
	return tot;
}

void pushup(int x){
	sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+cnt[x];
}

//加入inf和-inf 便于操作 
void init(){
	int x=get_new(-inf);
	int y=get_new(inf);
	fa[y]=x;
	ch[x][1]=y;
	rt=x;
	pushup(y);
	pushup(x);
}

void rotate(int x){
	int y=fa[x],z=fa[y];
	int k=(ch[y][1]==x);//x是左儿子还是右儿子
	int w=ch[x][k^1];//旋转后左儿子变右儿子,右儿子变左儿子
	if(z) ch[z][ch[z][1]==y]=x;
	fa[x]=z;
	fa[fa[ch[ch[x][k^1]=y][k]=w]=y]=x;
	pushup(y);
	pushup(x);
} 

//每次在树上遍历都要splay! 才能保证均摊复杂度 
void splay(int x,int gl){
	while(fa[x]!=gl){
		int y=fa[x],z=fa[y];
		if(z!=gl){
			if((ch[y][1]==x)==(ch[z][1]==y)) rotate(y);
			else rotate(x);
		}
		rotate(x);
	}
	if(gl==0) rt=x;
}

//w这个结点,返回的是结点编号;没有,返回的是前驱或者后继。
int get_id(int v){
	int x=rt;
	while(val[x]!=v && ch[x][v>val[x]]){
		x=ch[x][v>val[x]];
	}
	splay(x,0);
	return x;
}

//找到权值为v的数的前驱的编号 
int get_pre(int v){
	int x=get_id(v);
	if(val[x]<v) return x;
	splay(x,0);
	x=ch[x][0];
	while(ch[x][1]) x=ch[x][1];
	splay(x,0);
	return x;
}

//找到权值为v的数的后继的编号
int get_suf(int v){
	int x=get_id(v);
	if(val[x]>v) return x;
	splay(x,0);
	x=ch[x][1];
	while(ch[x][0]) x=ch[x][0];
	splay(x,0);
	return x;
}

void Insert(int v){
	int x=rt,y;
	while(x && val[x]!=v){
		y=x;
		x=ch[x][v>val[x]];
	}
	if(x){
		cnt[x]++;
	}else{
		x=get_new(v);
		fa[x]=y;
		ch[y][v>val[y]]=x;
	}
	splay(x,0);
}

void Delete(int v){
	int suf=get_suf(v);
	int pre=get_pre(v);
	splay(pre,0);
	splay(suf,pre);
	int x=ch[suf][0];
	if(x==0) return;
	cnt[x]--;
	pushup(x);
	if(cnt[x]==0) ch[suf][0]=0;
	pushup(suf);
	pushup(pre);
}

int get_kth(int v){
	int x=get_id(v);
	splay(x,0);
	return  sz[ch[x][0]]+(val[x]<v)*cnt[x]+1;
}

int get_val(int k){
	int x=rt;
	while(true){
		if(sz[ch[x][0]]>=k){
			x=ch[x][0];
		}else if(sz[ch[x][0]]+cnt[x]<k){
			k-=sz[ch[x][0]]+cnt[x];
			x=ch[x][1];
		}else{
			splay(x,0);
			return val[x];
		}
	}
}

int main(){
	init();
	n=read();
	int op,v;
	while(n--){
		op=read();
		v=read();
		if(op==1){
			Insert(v);
		}else if(op==2){
			Delete(v);
		}else if(op==3){
			printf("%d\n",get_kth(v)-1);//因为插入了-inf 所以实际要-1 
		}else if(op==4){
			printf("%d\n",get_val(v+1));//同理
		}else if(op==5){
			printf("%d\n",val[get_pre(v)]);
		}else{
			printf("%d\n",val[get_suf(v)]);
		}
	}
	return 0;
}

序列Splay

#include<bits/stdc++.h>
#define MAXN 100005
using namespace std;

inline long long read(){
	long long x=0;
	int f=1;
	char c=getchar();
	while(c<'0' || c>'9'){
		if(c=='-') f=-1;
		c=getchar();
	}
	while(c>='0' && c<='9'){
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return x*f;
}

int n,m;
int fa[MAXN],ch[MAXN][5], val[MAXN],sz[MAXN],rv[MAXN];
int rt,tot;
const int inf=0x7fffffff;

int get_new(int v){
	tot++;
	fa[tot]=ch[tot][0]=ch[tot][1]=0;
	rv[tot]=0;
	sz[tot]=1;
	val[tot]=v;
	return tot;
}

void pushup(int x){
	sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1;
}

void init(){
	int x=get_new(inf);
	int y=get_new(-inf);
	rt=x;
	ch[x][0]=y;
	fa[y]=x;
	pushup(y);
	pushup(x);
}

void rotate(int x){
	int y=fa[x],z=fa[y];
	int k=(ch[y][1]==x);
	int w=ch[x][k^1];
	if(z) ch[z][ch[z][1]==y]=x;
	fa[x]=z;
	fa[fa[ch[ch[x][k^1]=y][k]=w]=y]=x;
	pushup(y);
	pushup(x);
}

void splay(int x,int gl){
	while(fa[x]!=gl){
		int y=fa[x],z=fa[y];
		if(z!=gl){
			if((ch[y][1]==x)==(ch[z][1]==y)) rotate(y);
			else rotate(x);
		}
		rotate(x);
	}
	if(gl==0) rt=x;
}

void make_rv(int x){
	rv[x]^=1;
	swap(ch[x][0],ch[x][1]);
}

void pushdown(int x){
	if(rv[x]){
		make_rv(ch[x][0]);
		make_rv(ch[x][1]);
		rv[x]=0;
	}
}

int get_id(int k){
	int x=rt;
	while(true){
		//printf("!%d ",x);
		pushdown(x);
		if(sz[ch[x][0]]>=k){
			x=ch[x][0];
		}else if(sz[ch[x][0]]+1<k){
			k-=sz[ch[x][0]]+1;
			x=ch[x][1];
		}else{
			splay(x,0);
			return x;
		}
	}
}

void Insert(int v,int x){
	int pre=get_id(x);//-inf 实际代表k-1 
	int suf=get_id(x+1);
	//puts("!");
	splay(pre,0);
	splay(suf,pre);
	ch[suf][0]=get_new(v);
	fa[ch[suf][0]]=suf;
	//puts("!");
	pushup(x);
	pushup(suf);
	pushup(pre);
	//puts("!");
}

void calc(int l,int r){
	int pre=get_id(l-1);
	int suf=get_id(r+1);
	splay(pre,0);
	splay(suf,pre);
	make_rv(ch[suf][0]);
	pushup(suf);
	pushup(pre);
}

void dfs(int x){
	if(x==0) return;
	pushdown(x);
	dfs(ch[x][0]);
	if(val[x]<=n && val[x]>=1) printf("%d ",val[x]);
	dfs(ch[x][1]);
} 

int main(){
	init();
	n=read();m=read();
	for(int i=1;i<=n;i++){
		//printf("%d ",i);
		Insert(i,i);
	}
	int l,r;
	while(m--){
		l=read();r=read();
		calc(l+1,r+1);//-inf 
	}
	dfs(rt);
	return 0;
}

可持久化序列线段树

#include<bits/stdc++.h>
#define MAXN 1000005
using namespace std;

inline int read(){
	int x=0;
	int f=1;
	char c=getchar();
	while(c<'0' || c>'9'){
		if(c=='-') f=-1;
		c=getchar();
	}
	while(c>='0' && c<='9'){
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return x*f;
}

int n,m;
int a[MAXN];
struct node{
	int ls,rs;
	int val;
}t[MAXN<<5];
int rt[MAXN],tot;

void build(int &k,int l,int r){
	k=++tot;
	if(l==r){
		t[k].val=a[l];
		return;
	}
	int mid=(l+r)>>1;
	build(t[k].ls,l,mid);
	build(t[k].rs,mid+1,r);
}

void update(int &k,int pre,int l,int r,int p,int v){
	k=++tot;
	t[k]=t[pre];
	if(l==r){
		t[k].val=v;
		return;
	}
	int mid=(l+r)>>1;
	if(mid>=p) update(t[k].ls,t[pre].ls,l,mid,p,v);
	else update(t[k].rs,t[pre].rs,mid+1,r,p,v);
}

int query(int k,int l,int r,int p){
	if(l==r){
		return t[k].val;
	}
	int mid=(l+r)>>1;
	if(mid>=p) return query(t[k].ls,l,mid,p);
	else return query(t[k].rs,mid+1,r,p);
}

int main(){
	n=read();m=read();
	for(int i=1;i<=n;i++){
		a[i]=read();
	}
	build(rt[0],1,n);
	int pre,op,x,v;
	for(int i=1;i<=m;i++){
		pre=read();op=read();
		if(op==1){
			x=read();v=read();
			update(rt[i],rt[pre],1,n,x,v);
		}else{
			x=read();
			printf("%d\n",query(rt[pre],1,n,x));
			rt[i]=rt[pre];
		}
	}
}
//请保持心脏震动,等待有人与你共鸣

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

#include<bits/stdc++.h>
#define MAXN 200005
using namespace std;

inline int read(){
	int x=0;
	int f=1;
	char c=getchar();
	while(c<'0' || c>'9'){
		if(c=='-') f=-1;
		c=getchar();
	}
	while(c>='0' && c<='9'){
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return x*f;
}

int n,m;
int a[MAXN],lsh[MAXN],nn,aa[MAXN];
struct node{
	int ls,rs;
	long long sum;
}t[MAXN<<5];
int rt[MAXN],tot;

void build(int &k,int l,int r){
	k=++tot;
	if(l==r) return;
	int mid=(l+r)>>1;
	build(t[k].ls,l,mid);
	build(t[k].rs,mid+1,r);
}

void pushup(int k){
	t[k].sum=t[t[k].ls].sum+t[t[k].rs].sum;
} 

void update(int &k,int pre,int l,int r,int p,int v){
	k=++tot;
	t[k]=t[pre];
	if(l==r){
		t[k].sum+=v;
		return;
	}
	int mid=(l+r)>>1;
	if(mid>=p) update(t[k].ls,t[pre].ls,l,mid,p,v);
	if(mid<p) update(t[k].rs,t[pre].rs,mid+1,r,p,v);
	pushup(k);
}

int query(int x,int y,int l,int r,int k){
	if(l==r) return l;
	int sum=t[t[y].ls].sum-t[t[x].ls].sum;
	int mid=(l+r)>>1;
	if(sum>=k) return query(t[x].ls,t[y].ls,l,mid,k);
	else return query(t[x].rs,t[y].rs,mid+1,r,k-sum);
}

int main(){
	n=read();m=read();
	for(int i=1;i<=n;i++){
		a[i]=read();
		lsh[i]=a[i];
	}
	sort(lsh+1,lsh+1+n);
	nn=unique(lsh+1,lsh+1+n)-lsh-1;
	for(int i=1;i<=n;i++){
		a[i]=lower_bound(lsh+1,lsh+1+nn,a[i])-lsh;
	}
	build(rt[0],1,n);
	for(int i=1;i<=n;i++){
		update(rt[i],rt[i-1],1,nn,a[i],1);
	} 
	int l,r,k;
	while(m--){
		l=read();r=read();k=read();
		int ans=query(rt[l-1],rt[r],1,nn,k);
		printf("%d\n",lsh[ans]);
	}
	return 0;
}
//保持心脏震动,有人等你共鸣 

可持久化权值平衡树

#include<bits/stdc++.h>
#define MAXN 500005
using namespace std;

inline long long read(){
	long long x=0;
	int f=1; 
	char c=getchar();
	while(c<'0' || c>'9'){
		if(c=='-') f=-1;
		c=getchar();
	}
	while(c>='0' && c<='9'){
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return x*f;
}

int n,tot;
struct node{
	int val,key;//权值,堆值 
	int ls,rs;//左右儿子编号
	int sz;//大小,该元素数量 
}t[MAXN*50];
int rt[MAXN];

int get_new(int x){
	tot++;
	t[tot].val=x;
	t[tot].key=rand();
	t[tot].sz=1;
	return tot;
}

void pushup(int k){
	t[k].sz=t[t[k].ls].sz+t[t[k].rs].sz+1;
}

void split(int k,int &x,int &y,int ky){
	if(k==0){
		x=y=0;
		return;
	}
	if(t[k].val<=ky){
		x=get_new(0);
		t[x]=t[k];
		split(t[x].rs,t[x].rs,y,ky);
		pushup(x);
	}else{
		y=get_new(0);
		t[y]=t[k];
		split(t[y].ls,x,t[y].ls,ky);
		pushup(y);
	}
}

int merge(int x,int y){
	if(x*y==0){
		return x+y;
	}
	if(t[x].key>t[y].key){
		int k=get_new(0);
		t[k]=t[x];
		t[k].rs=merge(t[k].rs,y);
		pushup(k);
		return k;
	}else{
		int k=get_new(0);
		t[k]=t[y];
		t[k].ls=merge(x,t[k].ls);
		pushup(k);
		return k;
	}
}

int find(int rt,int num){
	int now=rt;
	while(true){
		if(t[t[now].ls].sz==num-1){
			return t[now].val;
		}else if(t[t[now].ls].sz<num-1){
			num-=t[t[now].ls].sz+1;
			now=t[now].rs;
		}else{
			now=t[now].ls;
		}		
	}
	return 0;
}

int main(){
	srand(9907);
	n=read();
	int id,op,v;
	int x,y,z;
	for(int i=1;i<=n;i++){
		id=read();op=read();v=read();
		rt[i]=rt[id];
		if(op==1){
			int nw=get_new(v);
			split(rt[i],x,y,v);
			rt[i]=merge(merge(x,nw),y);
		}else if(op==2){
			split(rt[i],x,z,v);
			split(x,x,y,v-1);
			y=merge(t[y].ls,t[y].rs);
			rt[i]=merge(merge(x,y),z);			
		}else if(op==3){
			split(rt[i],x,y,v-1);
			printf("%d\n",t[x].sz+1);
			rt[i]=merge(x,y);
		}else if(op==4){
			printf("%d\n",find(rt[i],v));
		}else if(op==5){
			split(rt[i],x,y,v-1);
			int now=x;
			while(t[now].rs) now=t[now].rs;
			printf("%d\n",t[now].val);
			rt[i]=merge(x,y);
		}else if(op==6){
			split(rt[i],x,y,v);
			int now=y;
			while(t[now].ls) now=t[now].ls;
			printf("%d\n",t[now].val);
			rt[i]=merge(x,y);			
		}
	}
	return 0;
}

可持久化序列平衡树

#include<bits/stdc++.h>
#define MAXN 200005
using namespace std;

inline long long read(){
	long long x=0;
	int f=1;
	char c=getchar();
	while(c<'0' || c>'9'){
		if(c=='-') f=-1;
		c=getchar();
	}
	while(c>='0' && c<='9'){
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return x*f;
}

int n,tot;
struct node{
	int ls,rs;
	long long val,sum,tag;
	int key,sz;
}t[MAXN*90];
int rt[MAXN];

int get_new(int v){
	tot++;
	t[tot].sum=t[tot].val=v;
	t[tot].key=rand();
	t[tot].sz=1;
	return tot;
}

void make_exchange(int k){
	t[k].tag^=1;
	swap(t[k].ls,t[k].rs);
}

void pushup(int k){
	t[k].sz=t[t[k].ls].sz+t[t[k].rs].sz+1;
	t[k].sum=t[t[k].ls].sum+t[t[k].rs].sum+t[k].val;
}

void pushdown(int k){
	if(t[k].tag){
		if(t[k].ls){
			int tmp=get_new(0);
			t[tmp]=t[t[k].ls];
			t[k].ls=tmp;
			make_exchange(t[k].ls);
		}
		if(t[k].rs){
			int tmp=get_new(0);
			t[tmp]=t[t[k].rs];
			t[k].rs=tmp;
			make_exchange(t[k].rs);
		}		
		t[k].tag=0;
	}
}

void split(int k,int &x,int &y,int ky){
//	printf("%d %d %d %d\n",k,x,y,ky);
	if(k==0){
		x=y=0;
		return;
	}
	pushdown(k);
	if(t[t[k].ls].sz+1<=ky){
		x=get_new(0);
		t[x]=t[k];
		split(t[x].rs,t[x].rs,y,ky-t[t[x].ls].sz-1);
		pushup(x);
	}else{
		y=get_new(0);
		t[y]=t[k];
		split(t[y].ls,x,t[y].ls,ky);
		pushup(y);
	}
}

int merge(int x,int y){
	if(x*y==0){
		return x+y;
	}
	pushdown(x);
	pushdown(y);
	if(t[x].key>t[y].key){
		int k=get_new(0);
		t[k]=t[x];
//		int k=x;
		t[k].rs=merge(t[k].rs,y);
		pushup(k);
		return k;
	}else{
		int k=get_new(0);
		t[k]=t[y];
//		int k=y;
		t[k].ls=merge(x,t[k].ls);
		pushup(k);
		return k;
	}
}

int main(){
	srand(9907);
	n=read();
	int id,op;
	long long p,v,l,r;
	long long ans=0;
	int x,y,z;
	for(int i=1;i<=n;i++){
		id=read();op=read();
		rt[i]=rt[id];
		if(op==1){
			p=read();v=read();
			p^=ans;v^=ans;
			int nw=get_new(v);
			split(rt[i],x,y,p);
			rt[i]=merge(merge(x,nw),y);
		}else if(op==2){
			p=read();
			p^=ans;
			split(rt[i],x,z,p);
			split(x,x,y,p-1);
			rt[i]=merge(x,z);
		}else if(op==3){
			l=read();r=read();
			l^=ans;r^=ans;
			split(rt[i],x,z,r);
			split(x,x,y,l-1);
			make_exchange(y);
			rt[i]=merge(merge(x,y),z);
		}else if(op==4){
			l=read();r=read();
			l^=ans;r^=ans;
//			printf("l=%d r=%d\n",l,r);
			split(rt[i],x,z,r);
			split(x,x,y,l-1);
			ans=t[y].sum;
			printf("%lld\n",ans);
			rt[i]=merge(merge(x,y),z);
		}
	}
	return 0;
}

可持久化0-1trie

#include<bits/stdc++.h>
#define MAXN 600005
using namespace std;

inline long long read(){
	long long x=0;
	int f=1;
	char c=getchar();
	while(c<'0' || c>'9'){
		if(c=='-') f=-1;
		c=getchar();
	}
	while(c>='0' && c<='9'){
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return x*f;
}

int n,m,tot;
int a[MAXN],sum[MAXN];
struct node{
	int ch[2];
	int val;
}t[MAXN*25];
int rt[MAXN];

void insert(int k,int pre,int v){
	for(int i=25;i>=0;i--){
		int s=(v>>i)&1;	
		t[k].ch[!s]=t[pre].ch[!s];
		t[k].ch[s]=++tot;	
		t[t[k].ch[s]].val=t[t[pre].ch[s]].val+1;
		k=t[k].ch[s];
		pre=t[pre].ch[s];		
	}
}

int query(int x,int y,int v){
	int res=0;
	for(int i=25;i>=0;i--){
		int s=(v>>i)&1;
//		printf("! %d %d\n",t[t[y].ch[!s]].val,t[t[x].ch[!s]].val);
		if(t[t[y].ch[!s]].val>t[t[x].ch[!s]].val){
			res+=(1<<i);
			x=t[x].ch[!s];
			y=t[y].ch[!s];			
		}else{
			x=t[x].ch[s];
			y=t[y].ch[s];				
		}
	}
	return res;
}

int main(){
	n=read();m=read();
	for(int i=1;i<=n;i++){
		a[i]=read();
		sum[i]=sum[i-1]^a[i];
		rt[i]=++tot;
		insert(rt[i],rt[i-1],sum[i]);
	}
	char op[5];
	int l,r,x;
	while(m--){
		scanf("%s",op);
		if(op[0]=='A'){
			x=read();
			a[++n]=x;
			sum[n]=sum[n-1]^a[n];
			rt[n]=++tot;
			insert(rt[n],rt[n-1],sum[n]);
		}else{
			l=read();r=read();
			x=read();
			l--;r--;
			int ans=0;
			if(l==0) ans=max(query(0,rt[r],sum[n]^x),sum[n]^x);
			else ans=query(rt[l-1],rt[r],sum[n]^x);
			printf("%d\n",ans);
		}
	}
	return 0;
}

可持久化并查集

#include<bits/stdc++.h>
#define MAXN 200005
using namespace std;

inline int read(){
	int x=0;
	int f=1;
	char c=getchar();
	while(c<'0' || c>'9'){
		if(c=='-') f=-1;
		c=getchar();
	}
	while(c>='0' && c<='9'){
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return x*f;
}

int n,m;

struct node{
	int ls,rs;
	int val;
}t[MAXN<<5];
int rtfa[MAXN],rtdep[MAXN],tot;

void build(int &k,int l,int r){
	k=++tot;
	if(l==r){
		t[k].val=l;
		return;
	}
	int mid=(l+r)>>1;
	build(t[k].ls,l,mid);
	build(t[k].rs,mid+1,r);
}

void update(int &k,int pre,int l,int r,int p,int v){
	k=++tot;
	t[k]=t[pre];
	if(l==r){
		t[k].val=v;
		return;
	}
	int mid=(l+r)>>1;
	if(mid>=p) update(t[k].ls,t[pre].ls,l,mid,p,v);
	if(mid<p) update(t[k].rs,t[pre].rs,mid+1,r,p,v);
}

int query(int k,int l,int r,int p){
	if(l==r) return t[k].val;
	int mid=(l+r)>>1;
	if(mid>=p) return query(t[k].ls,l,mid,p);
	if(mid<p) return query(t[k].rs,mid+1,r,p);
}	

int find(int id,int x){
	int fx=query(rtfa[id],1,n,x);
	if(fx==x) return fx;
	else return find(id,fx);
}

void merge(int id,int x,int y){
	x=find(id-1,x);
	y=find(id-1,y);
	if(x==y){
		rtfa[id]=rtfa[id-1];
		rtdep[id]=rtdep[id-1];
		return;
	}
	int depx=query(rtdep[id-1],1,n,x);
	int depy=query(rtdep[id-1],1,n,y);
	if(depx==depy){
		update(rtfa[id],rtfa[id-1],1,n,y,x);
		update(rtdep[id],rtdep[id-1],1,n,x,depx+1);
	}else{
		if(depx<depy) swap(x,y);
		update(rtfa[id],rtfa[id-1],1,n,y,x);
		rtdep[id]=rtdep[id-1];
	}	
}

int main(){
	n=read();m=read();
	build(rtfa[0],1,n);
	int op,a,b;
	for(int i=1;i<=m;i++){
		op=read();
		if(op==1){
			a=read();b=read();
			merge(i,a,b);
		}else if(op==2){
			a=read();	
			rtfa[i]=rtfa[a];
			rtdep[i]=rtdep[a];
		}else{
			a=read();b=read();
			rtfa[i]=rtfa[i-1];
			rtdep[i]=rtdep[i-1];
			a=find(i,a);
			b=find(i,b);
			if(a==b) puts("1");
			else puts("0");
		}
	}
	return 0;
}

序列线段树套权值平衡树

#include<bits/stdc++.h>
#define MAXN 50005
using namespace std;

inline int read(){
	int x=0;
	char c=getchar();
	while(c<'0' || c>'9'){
		c=getchar();
	}
	while(c>='0' && c<='9'){
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return x;
}

int n,m,tot;
int a[MAXN];
struct node{
	int ls,rs;
	int val,key,sz;
}t[MAXN*100];

struct FHQ_Treap{
	int rt,x,y,z;
	int get_new(int v){
		tot++;
		t[tot].val=v;
		t[tot].key=rand();
		t[tot].sz=1;
		return tot;
	}
	void pushup(int k){
		t[k].sz=t[t[k].ls].sz+t[t[k].rs].sz+1;
	}
	void split(int k,int &x,int &y,int ky){
		if(!k){
			x=y=0;
			return;
		}
		if(t[k].val<=ky){
			x=k;
			split(t[k].rs,t[x].rs,y,ky);
		}else{
			y=k;
			split(t[k].ls,x,t[y].ls,ky);
		}
		pushup(k);
	}
	int merge(int x,int y){
		if(x*y==0){
			return x+y;
		}
		int k; 
		if(t[x].key>t[y].key){
			k=x;
			t[k].rs=merge(t[x].rs,y);
		}else{
			k=y;
			t[k].ls=merge(x,t[y].ls);
		}
		pushup(k);
		return k;
	}
	void insert(int v){
		int nw=get_new(v);
		split(rt,x,y,v);
		rt=merge(merge(x,nw),y);
	}
	void Delete(int v){
		split(rt,x,z,v);
		split(x,x,y,v-1);
		y=merge(t[y].ls,t[y].rs);
		rt=merge(merge(x,y),z);
	}
	int get_rank(int v){
		split(rt,x,y,v-1);
		int res=t[x].sz+1;
		rt=merge(x,y);
		return res;
	}
	int get_pre(int v){
		split(rt,x,y,v-1);
		int res;
		if(!x){
			res=-2147483647;
		}else{
			int now=x;
			while(t[now].rs) now=t[now].rs;
			res=t[now].val;
		}		
		rt=merge(x,y);
		return res;
	}
	int get_suf(int v){
		split(rt,x,y,v);
		int res;
		if(!y){
			res=2147483647;
		}else{
			int now=y;
			while(t[now].ls) now=t[now].ls;
			res=t[now].val;
		}	
		rt=merge(x,y);
		return res;
	}
}BT[MAXN<<2];

struct segment_tree{
	#define ls k<<1
	#define rs k<<1|1
	struct node{
		int l,r;
	}t[MAXN<<2];
	void build(int k,int l,int r){
		t[k].l=l;t[k].r=r;
		for(int i=l;i<=r;i++){
			BT[k].insert(a[i]);
		}
		if(l==r) return;
		int mid=(l+r)>>1;
		build(ls,l,mid);
		build(rs,mid+1,r);
	}
	void update(int k,int p,int v){
		BT[k].Delete(a[p]);
		BT[k].insert(v);
		if(t[k].l==t[k].r) return;
		int mid=(t[k].l+t[k].r)>>1;
		if(mid>=p) update(ls,p,v);
		if(mid<p) update(rs,p,v); 
	}
	int get_rank(int k,int l,int r,int v){
		if(t[k].l>=l && t[k].r<=r){
			return BT[k].get_rank(v)-1;
		}
		int mid=(t[k].l+t[k].r)>>1;
		int res=0;
		if(mid>=l) res+=get_rank(ls,l,r,v);
		if(mid<r) res+=get_rank(rs,l,r,v);
		return res;
	}
	int get_val(int L,int R,int v){
		int l=0,r=1e8,mid;
		int res=0;
		while(l<=r){
			mid=(l+r)>>1;
			int num=get_rank(1,L,R,mid)+1;
			if(num<=v){
				res=mid;
				l=mid+1;
			}else{
				r=mid-1;
			}
		}
		return res;
	}
	int get_pre(int k,int l,int r,int v){
		if(t[k].l>=l && t[k].r<=r){
			return BT[k].get_pre(v);
		}
		int mid=(t[k].l+t[k].r)>>1;
		int res=-2147483647;
		if(mid>=l) res=max(res,get_pre(ls,l,r,v));
		if(mid<r) res=max(res,get_pre(rs,l,r,v));
		return res;
	} 
	int get_suf(int k,int l,int r,int v){
		if(t[k].l>=l && t[k].r<=r){
			return BT[k].get_suf(v);
		}
		int mid=(t[k].l+t[k].r)>>1;
		int res=2147483647;
		if(mid>=l) res=min(res,get_suf(ls,l,r,v));
		if(mid<r) res=min(res,get_suf(rs,l,r,v));
		return res;
	}
	#undef ls
	#undef rs
}ST;
 
int main(){
	srand(time(0));
	n=read();m=read();
	for(int i=1;i<=n;i++){
		a[i]=read();
	}
	ST.build(1,1,n);
	int op,l,r,k,p;
	while(m--){
		op=read();
		if(op==1){
			l=read();r=read();k=read();
			printf("%d\n",ST.get_rank(1,l,r,k)+1);
		}else if(op==2){
			l=read();r=read();k=read();
			printf("%d\n",ST.get_val(l,r,k));
		}else if(op==3){
			p=read();k=read();
			ST.update(1,p,k);
			a[p]=k;
		}else if(op==4){
			l=read();r=read();k=read();
			printf("%d\n",ST.get_pre(1,l,r,k));
		}else{
			l=read();r=read();k=read();
			printf("%d\n",ST.get_suf(1,l,r,k));
		}
	}
}
//祝你先于春天,翻过此间铮铮山峦 

序列树状数组套权值线段树

#include<bits/stdc++.h>
#define MAXN 20005
using namespace std;

inline int read(){
	int x=0;
	char c=getchar();
	while(c<'0' || c>'9'){
		c=getchar();
	}
	while(c>='0' && c<='9'){
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return x;
}

int n,m,tot;
int a[MAXN],lsh[MAXN],nn;
struct node{
	int ls,rs;
	int sz;
}t[MAXN*100];
int rt[MAXN];

struct segment_tree{//权值线段树 
	void pushup(int k){
		t[k].sz=t[t[k].ls].sz+t[t[k].rs].sz; 
	}
	void update(int &k,int l,int r,int p,int v){
		if(!k) k=++tot;
		if(l==r){
			t[k].sz+=v;
			return;
		}
		int mid=(l+r)>>1;
		if(mid>=p) update(t[k].ls,l,mid,p,v);
		if(mid<p) update(t[k].rs,mid+1,r,p,v);
		pushup(k);
	}
	int query(int k,int l,int r,int L,int R){
		if(!k) return 0;
		if(l>=L && r<=R){
			return t[k].sz;
		}
		int mid=(l+r)>>1;
		int res=0;
		if(mid>=L) res+=query(t[k].ls,l,mid,L,R);
		if(mid<R) res+=query(t[k].rs,mid+1,r,L,R);
		return res;
	}
}ST;

struct tree_array{//序列树状数组
	int lowbit(int x){
		return x&(-x);
	} 
	void update(int x,int p,int v){
		for(;x<=n;x+=x&(-x)){
			ST.update(rt[x],1,nn,p,v);
		}
	} 
	int ask(int x,int l,int r){
		int res=0;
		for(;x;x-=x&(-x)){
			res+=ST.query(rt[x],1,nn,l,r);
		}
		return res;
	}
	int query(int l,int r,int nl,int nr){
		if(r<l) return 0;
		if(nr<nl) return 0;
		int res=ask(r,nl,nr)-ask(l-1,nl,nr);
		return res;
	}
}BIT;

int main(){
	n=read();
	for(int i=1;i<=n;i++){
		a[i]=read();
		lsh[i]=a[i];		
	}
	sort(lsh+1,lsh+1+n);
	nn=unique(lsh+1,lsh+1+n)-lsh-1;
	int ans=0;
	for(int i=1;i<=n;i++){
		a[i]=lower_bound(lsh+1,lsh+1+nn,a[i])-lsh;
		BIT.update(i,a[i],1);
		ans+=BIT.query(1,i-1,a[i]+1,nn);
	}
	printf("%d\n",ans);
	m=read();
	int x,y;
	while(m--){
		x=read();y=read();
		if(x>y) swap(x,y);
		ans-=BIT.query(x+1,y-1,1,a[x]-1);
		ans+=BIT.query(x+1,y-1,a[x]+1,nn);
		ans-=BIT.query(x+1,y-1,a[y]+1,nn);
		ans+=BIT.query(x+1,y-1,1,a[y]-1);
		if(a[x]<a[y]) ans++;
		if(a[x]>a[y]) ans--;
		BIT.update(x,a[x],-1);
		BIT.update(x,a[y],1);
		BIT.update(y,a[x],1);
		BIT.update(y,a[y],-1);
		swap(a[x],a[y]);
		printf("%d\n",ans);
	}
	return 0;
} 
//醉后不知天在水,满船清梦压星河 

点分治

#include<bits/stdc++.h>
#define MAXN 10005
using namespace std;

inline long long read(){
	long long x=0;
	char c=0;
	while(c<'0' || c>'9'){
		c=getchar();
	}
	while(c>='0' && c<='9'){
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return x;
}

int n,m;
struct node{
	int to,val;
};
vector<node> edge[MAXN];
int sz[MAXN],wt[MAXN];
int root,SZ;
bool vis[MAXN];
int dis[MAXN],tmp[MAXN],cnt;
int q[MAXN];
struct nd{
	int dis;
	int id,belong;
}a[MAXN];
bool ans[MAXN];

void get_root(int x,int f){
	sz[x]=1;
	wt[x]=0;
	for(int i=0;i<edge[x].size();i++){
		int y=edge[x][i].to;
		if(y==f || vis[y]) continue;
		get_root(y,x);
		sz[x]+=sz[y];
		wt[x]=max(wt[x],sz[y]);
	}
	wt[x]=max(wt[x],SZ-sz[x]);
	if(wt[x]<wt[root]){
		root=x;
	}
	return;
}

void get_dis(int x,int f,int sum,int from){
	a[++cnt].dis=sum;
	a[cnt].id=x;
	a[cnt].belong=from;
	for(int i=0;i<edge[x].size();i++){
		int y=edge[x][i].to;
		int w=edge[x][i].val;
		if(y==f || vis[y]) continue;
		get_dis(y,x,sum+w,from);
	}
	return;
}

bool cmp(nd aa,nd bb){
	return aa.dis<bb.dis;
}

void calc(int x){
	cnt=0;
	a[++cnt].dis=0;
	a[cnt].id=x;
	a[cnt].belong=x;
	for(int i=0;i<edge[x].size();i++){
		int y=edge[x][i].to;
		int w=edge[x][i].val;
		if(vis[y]) continue;
		get_dis(y,x,w,y);
	}
	sort(a+1,a+1+cnt,cmp);
	for(int i=1;i<=m;i++){
		if(ans[i]) continue;
		int l=1,r=cnt;
		while(l<r){
			if(a[l].dis+a[r].dis>q[i]){
				r--;
			}else if(a[l].dis+a[r].dis<q[i]){
				l++;
			}else{
				if(a[l].belong==a[r].belong){
					if(a[l].dis==a[l+1].dis) l++;
					else r--;
				}else{
					ans[i]=true;
					break;
				}
			}
		}
	}
	return;
}

void Divide(int x){
	vis[x]=true;
	calc(x);
	int Sz=SZ;
	for(int i=0;i<edge[x].size();i++){
		int y=edge[x][i].to;
		if(vis[y]) continue;
		SZ=(sz[y]<sz[x]) ? sz[y] : (Sz-sz[x]);
		root=0;
		get_root(y,0);
		Divide(root);
	}
	return;
}

int main(){
	n=read();m=read();
	int u,v,w;
	for(int i=1;i<n;i++){
		u=read();v=read();w=read();
		edge[u].push_back((node){v,w});
		edge[v].push_back((node){u,w});
	}
	for(int i=1;i<=m;i++){
		q[i]=read();
	}
	wt[0]=n;
	SZ=n;
	get_root(1,0);
	Divide(root);
	for(int i=1;i<=m;i++){
		if(ans[i]) puts("AYE");
		else puts("NAY");
	}
	return 0;
}

点分树

#include<bits/stdc++.h>
#define MAXN 100005
using namespace std;

inline int read(){
	int x=0;
	char c=getchar();
	while(c<'0' || c>'9'){
		c=getchar();
	}
	while(c>='0' && c<='9'){
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return x;
}

int n,m;
int a[MAXN];
vector<int> edge[MAXN];
int dep[MAXN],sz[MAXN],wt[MAXN],SZ,rt;
bool vis[MAXN];
int fa[MAXN],ffa[MAXN][25];
vector<int> cs[MAXN],cf[MAXN];

void dfs(int x,int f){
	ffa[x][0]=f;
	dep[x]=dep[f]+1;
	for(auto y:edge[x]){
		if(y==f) continue;
		dfs(y,x);
	}
}

void init(){
	for(int j=1;j<=21;j++){
		for(int i=1;i<=n;i++){
			ffa[i][j]=ffa[ffa[i][j-1]][j-1];
		}
	}
}

int LCA(int a,int b){
	if(dep[a]<dep[b]) swap(a,b);
	int step=dep[a]-dep[b];
	for(int i=0;i<=20;i++){
		if(step&(1<<i)){
			a=ffa[a][i];
		}
	}
	if(a==b) return a;
	for(int i=20;i>=0;i--){
		if(ffa[a][i]!=ffa[b][i]){
			a=ffa[a][i];
			b=ffa[b][i];
		}
	}
	return ffa[a][0];
} 

int get_dis(int u,int v){
	int lca=LCA(u,v);
	return dep[u]+dep[v]-2*dep[lca];
}

int lowbit(int x){
	return x&(-x);
}

void update(int op,int id,int x,int v){
	int nn=op ? cs[id].size() : cf[id].size(); 
	for(;x<nn;x+=lowbit(x)){
		if(op==1) cs[id][x]+=v;
		else cf[id][x]+=v;
	}
}

int query(int op,int id,int x){
	int res=0;
	x=min(x,op?(int)cs[id].size()-1:(int)cf[id].size()-1);
	for(;x>0;x-=lowbit(x)){
		if(op==1) res+=cs[id][x];
		else res+=cf[id][x];
	}
	return res;
}

void upd(int x,int v){
	int p=x;
	while(p){
		update(1,p,get_dis(x,p)+1,v);
		if(fa[p]) update(0,p,get_dis(x,fa[p])+1,v);
		p=fa[p];
	}
}

int ask(int x,int y){
	int res=0;
	int p=x;
	while(p){
		res+=query(1,p,y-get_dis(x,p)+1);
		if(fa[p]) res-=query(0,p,y-get_dis(fa[p],x)+1);
		p=fa[p];
	}
	return res;
}

void get_sz(int x,int f){
	sz[x]=1;
	for(auto y:edge[x]){
		if(y==f || vis[y]) continue;
		get_sz(y,x);
		sz[x]+=sz[y];
	}
}

void get_rt(int x,int f){
	wt[x]=0;
	for(auto y:edge[x]){
		if(y==f || vis[y]) continue;
		get_rt(y,x);
		wt[x]=max(wt[x],sz[y]);
	}
	wt[x]=max(wt[x],SZ-sz[x]);
	if(wt[x]<wt[rt]) rt=x;
}

int daco(int x){
	get_sz(x,0);
	SZ=sz[x],rt=0;
	get_rt(x,0);
	int r=rt;
	vis[r]=true;
	cs[r].resize(SZ+2);
	cf[r].resize(SZ+2);
	for(auto y:edge[r]){
		if(vis[y]) continue;
		int tmp=daco(y);
		fa[tmp]=r;
	}
	return r;
}

int main(){
	n=read();m=read();
	for(int i=1;i<=n;i++){
		a[i]=read();
	}
	int u,v;
	for(int i=1;i<n;i++){
		u=read();v=read();
		edge[v].push_back(u);
		edge[u].push_back(v);
	}
	dfs(1,0);
	init();
	wt[0]=n;
	daco(1);
	for(int i=1;i<=n;i++){
		upd(i,a[i]);
	}
	int op,x,y;
	int ans=0;
	while(m--){
		op=read();
		x=read();y=read();
		x^=ans;y^=ans;
		if(op==0){
			ans=ask(x,y);
			printf("%d\n",ans);
		}else{
			upd(x,y-a[x]);
			a[x]=y;
		}
	}
	return 0;
}

K-D Tree

邻域查询(算法复杂度没有保证 最坏 \(O(n)\)

#include<bits/stdc++.h>
#define MAXN 100005
using namespace std;

inline int read(){
	int x=0;
	char c=getchar();
	while(c<'0' || c>'9'){
		c=getchar();
	}
	while(c>='0' && c<='9'){
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return x;
}

int n;
struct point{
	double x[2];
}a[MAXN];
struct node{
	int ls,rs;
	point x;
	double D[2],U[2];
	int id;
}t[MAXN];
int tot,rt;
double ans1=1e9,ans2;
const double inf=1ll<<32;
double mn=inf,mx;

bool cmp0(point aa,point bb){
	return aa.x[0]<bb.x[0];
}

bool cmp1(point aa,point bb){
	return aa.x[1]<bb.x[1];
}

void pushup(int k){
	for(int i=0;i<=1;i++){
		t[k].D[i]=min(t[k].x.x[i],min(t[t[k].ls].D[i],t[t[k].rs].D[i]));
		t[k].U[i]=max(t[k].x.x[i],max(t[t[k].ls].U[i],t[t[k].rs].U[i]));
	}
}

void build(int &k,int l,int r,int dm){
	if(l>r) return;
	k=++tot;
	int mid=(l+r)>>1;
	if(!dm) nth_element(a+l,a+mid,a+r+1,cmp0);
	else nth_element(a+l,a+mid,a+r+1,cmp1); 
	t[k].x=a[mid];
	t[k].id=mid;
	build(t[k].ls,l,mid-1,dm^1);
	build(t[k].rs,mid+1,r,dm^1);
	pushup(k);
}

double get_mndis(int k,point y){
	double res=0;
	for(int i=0;i<=1;i++){
		if(y.x[i]<t[k].D[i]) res+=(t[k].D[i]-y.x[i])*(t[k].D[i]-y.x[i]);
		if(y.x[i]>t[k].U[i]) res+=(y.x[i]-t[k].U[i])*(y.x[i]-t[k].U[i]);
	}
	return res;
}

double get_mxdis(int k,point y){
	double res=0;
	for(int i=0;i<=1;i++){
		double tmp=max((t[k].D[i]-y.x[i])*(t[k].D[i]-y.x[i]),(y.x[i]-t[k].U[i])*(y.x[i]-t[k].U[i]));
		res+=tmp;
	}
	return res;
}

double get_dis(point x,point y){
	double res=0;
	for(int i=0;i<=1;i++){
		res+=(x.x[i]-y.x[i])*(x.x[i]-y.x[i]);
	}
	return res;
}

void query_min(int k,point p,int dm,int id){
	if(!k) return;
	if(get_mndis(k,p)>=mn) return;
	double dis=get_dis(t[k].x,p);
	double dis1=get_mndis(t[k].ls,p);
	double dis2=get_mndis(t[k].rs,p);
	if(t[k].id!=id) mn=min(mn,dis);
	if(dis1<dis2){
		if(dis1<mn) query_min(t[k].ls,p,dm^1,id);
		if(dis2<mn) query_min(t[k].rs,p,dm^1,id);
	}else{
		if(dis2<mn) query_min(t[k].rs,p,dm^1,id);
		if(dis1<mn) query_min(t[k].ls,p,dm^1,id);
	}
}

void query_max(int k,point p,int dm,int id){
	if(!k) return;
	if(get_mxdis(k,p)<=mx) return;
	double dis=get_dis(t[k].x,p);
	double dis1=get_mxdis(t[k].ls,p);
	double dis2=get_mxdis(t[k].rs,p);
	if(t[k].id!=id) mx=max(mx,dis);
	if(dis1>dis2){
		if(dis1>mx) query_max(t[k].ls,p,dm^1,id);
		if(dis2>mx) query_max(t[k].rs,p,dm^1,id);
	}else{
		if(dis2>mn) query_max(t[k].rs,p,dm^1,id);
		if(dis1>mn) query_max(t[k].ls,p,dm^1,id);
	}
}

int main(){
	n=read();
	for(int i=1;i<=n;i++){
		scanf("%lf %lf",&a[i].x[0],&a[i].x[1]);	
	}
	t[0].D[0]=t[0].D[1]=inf;
	t[0].U[0]=t[0].U[1]=-inf;
	build(rt,1,n,0);
	for(int i=1;i<=n;i++){
		query_min(rt,a[i],0,i);
		query_max(rt,a[i],0,i);
	}
	printf("%.2f %.2f\n",sqrt(mn),sqrt(mx));
	return 0;
}

矩形查询+二进制分组修改

#include<bits/stdc++.h>
#define MAXN 200005
using namespace std;

inline int read(){
	int x=0;
	char c=getchar();
	while(c<'0' || c>'9'){
		c=getchar();
	}
	while(c>='0' && c<='9'){
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return x;
}

int n;
struct point{
	int x[2];
	int val;
	point make_point(int ax,int ay,int v){
		point tmp;
		tmp.x[0]=ax;tmp.x[1]=ay;tmp.val=v;
		return tmp;
	}
}a[MAXN];
struct node{
	point x;
	int sum;
	int ls,rs;
	int D[2],U[2];
}t[MAXN];
int rt[25],tot,bn[MAXN],dcnt,cnt;
int ans;
const int inf=1e9;

int get_new(){
	if(dcnt) return bn[dcnt--];
	else return ++tot;
}

void del(int &k){
	t[k].ls=t[k].rs=t[k].sum=0;
	bn[++dcnt]=k;
	k=0;
}

int kk;
bool cmp(point aa,point bb){
	return aa.x[kk]<bb.x[kk];
}

void init(int &k){
	if(!k) return;
	a[++cnt]=t[k].x;
	init(t[k].ls);
	init(t[k].rs);
	del(k);
}

void pushup(int k){
	for(int i=0;i<=1;i++){
		t[k].D[i]=min(t[k].x.x[i],min(t[t[k].ls].D[i],t[t[k].rs].D[i]));
		t[k].U[i]=max(t[k].x.x[i],max(t[t[k].ls].U[i],t[t[k].rs].U[i]));
	}
	t[k].sum=t[t[k].ls].sum+t[t[k].rs].sum+t[k].x.val;
}

void build(int &k,int l,int r,int dm){
	if(l>r) return;
	k=get_new();
	int mid=(l+r)>>1;
	kk=dm;
	nth_element(a+l,a+mid,a+r+1,cmp);
	t[k].x=a[mid];
	build(t[k].ls,l,mid-1,dm^1);
	build(t[k].rs,mid+1,r,dm^1);
	pushup(k);
}

bool check(int x[],int y[]){
	int res=0;
	for(int i=0;i<=1;i++){
		if(x[i]<=y[i]) res++;
	}
	if(res==2) return true;
	else return false;
}

void query(int k,point d,point u,int dm){
	if(!k) return;
	if(!check(t[k].D,u.x) || !check(d.x,t[k].U)) return;
	if(check(d.x,t[k].D) && check(t[k].U,u.x)){
		ans+=t[k].sum;
		return;
	}
	if(check(d.x,t[k].x.x) && check(t[k].x.x,u.x)){
		ans+=t[k].x.val;
	}
	query(t[k].ls,d,u,dm^1);
	query(t[k].rs,d,u,dm^1);
}

int main(){
	n=read();
	int op,ax,ay,bx,by,v;
	t[0].D[0]=t[0].D[1]=inf;
	t[0].U[0]=t[0].U[1]=0;
	while(1){
		op=read();
		if(op==1){
			ax=read();ay=read();v=read();
			ax^=ans;ay^=ans;v^=ans;
			point tmp=tmp.make_point(ax,ay,v);
			t[++tot].x=tmp;
			cnt=0;
			a[++cnt]=tmp;
			for(int i=0;;i++){
				if(rt[i]){
					init(rt[i]);
				}else{
					build(rt[i],1,cnt,0);
					break;
				}
			}
		}else if(op==2){
			ax=read();ay=read();
			bx=read();by=read();
			ax^=ans;ay^=ans;bx^=ans;by^=ans;
			point aa={min(ax,bx),min(ay,by)};
			point bb={max(ax,bx),max(ay,by)};
			ans=0;
			for(int i=0;i<=20;i++){
				if(rt[i]) query(rt[i],aa,bb,0);
			}
			printf("%d\n",ans);
		}else if(op==3){
			break;	
		}	
	}
	return 0;
}

虚树

void build(){
	sort(q+1,q+1+k,cmp);
	top=0;
	st[++top]=q[1];
	for(int i=2;i<=k;i++){
		int lca=LCA(st[top],q[i]);
		while(dep[lca]<dep[st[top-1]]){
			add(st[top-1],st[top]);
			top--;
		}
		if(lca!=st[top]){
			add(lca,st[top]);
			if(lca!=st[top-1]) st[top]=lca;
			else top--;
		}
		st[++top]=q[i];
	}
	while(--top){
		add(st[top],st[top+1]);
	}
}

LCT

#include<bits/stdc++.h>
#define MAXN 100005
#define ls ch[x][0]
#define rs ch[x][1]
using namespace std;

inline int read(){
    int x=0;
    char c=getchar();
    while(c<'0' || c>'9'){
        c=getchar();
    }
    while(c>='0' && c<='9'){
        x=(x<<1)+(x<<3)+(c^48);
        c=getchar();
    }
    return x;
}

int n,m;
int fa[MAXN],ch[MAXN][3],val[MAXN],sum[MAXN],rv[MAXN];
stack<int> st;

bool notrt(int x){
	return ch[fa[x]][0]==x || ch[fa[x]][1]==x;
}

void pushup(int x){
	sum[x]=sum[ls]^sum[rs]^val[x];
}

void makerv(int x){
	rv[x]^=1;
	swap(ls,rs);
}

void pushdown(int x){
	if(rv[x]){
		if(ls) makerv(ls);
		if(rs) makerv(rs);
		rv[x]=0;
	}
} 

void pushdn(int x){
	while(!st.empty()) st.pop();
	st.push(x);
	while(notrt(x)){
		x=fa[x];
		st.push(x);
	}
	while(!st.empty()){
		pushdown(st.top());
		st.pop();
	}
}

void rotate(int x){
	int y=fa[x],z=fa[y];
	int k=(ch[y][1]==x);
	int w=ch[x][k^1];
	if(notrt(y)) ch[z][ch[z][1]==y]=x;
	fa[x]=z;
	fa[fa[ch[ch[x][k^1]=y][k]=w]=y]=x;
	pushup(y);
	pushup(x);
}

void splay(int x){
	pushdn(x);
	while(notrt(x)){
		int y=fa[x],z=fa[y];
		if(notrt(y)){
			if((ch[y][1]==x) == (ch[z][1]==y)) rotate(y);
			else rotate(x);
		}
		rotate(x);
	}
}

void access(int x){
	for(int y=0;x;y=x,x=fa[x]){
		splay(x);
		ch[x][1]=y;
		pushup(x);
	}
}

void makeroot(int x){
	access(x);
	splay(x);
	makerv(x);
}

int findroot(int x){
	access(x);
	splay(x);
	while(ls){
		pushdown(x);
		x=ls;
	}
	splay(x);
	return x;
}

void split(int x,int y){
	makeroot(x);
	access(y);
	splay(y);
}

void link(int x,int y){
	makeroot(x);
	if(findroot(y)!=x) fa[x]=y;
	pushup(y);
}

void cut(int x,int y){
	split(x,y);
	if(ch[y][0]!=x || ch[y][1]) return;
	ch[y][0]=fa[x]=0;
	pushup(y);
}

int main(){
	n=read();m=read();
	for(int i=1;i<=n;i++){
		val[i]=read();	
	} 
	int op,x,y;
	while(m--){
		op=read();
		x=read();y=read();
		if(op==0){
			split(x,y);
			printf("%d\n",sum[y]);
		}else if(op==1){
			link(x,y);
		}else if(op==2){
			cut(x,y);
		}else{
			splay(x);
			val[x]=y;
			pushup(x);
		}
	}
	return 0;
}

线段树分治

#include<bits/stdc++.h>
#define MAXN 400005
#define ls k<<1
#define rs k<<1|1
using namespace std;

inline int read(){
    int x=0;
    char c=getchar();
    while(c<'0' || c>'9'){
        c=getchar();
    }
    while(c>='0' && c<='9'){
        x=(x<<1)+(x<<3)+(c^48);
        c=getchar();
    }
    return x;
}

int n,m,k;
struct enode{
	int u,v;
}E[MAXN];
int fa[MAXN],sz[MAXN];
struct node{
	int l,r;
	int sum;
	vector<enode> v;
}t[MAXN<<2];
int w[MAXN];
int st[MAXN],top;

int find(int x){
	if(x==fa[x]) return fa[x];
	return find(fa[x]);
}

void merge(int x,int y){
	x=find(x);y=find(y);
	if(x!=y){
		if(sz[x]>sz[y]) swap(x,y);
		fa[x]=y; 
		sz[y]+=sz[x];
		st[++top]=x;
	}
}

void del(int x){
	sz[fa[x]]-=sz[x];
	fa[x]=x;
}

void build(int k,int l,int r){
	t[k].l=l;t[k].r=r;
	if(l==r) return;
	int mid=(l+r)>>1;
	build(ls,l,mid);
	build(rs,mid+1,r);
}

void update(int k,int l,int r,enode x){
	if(t[k].l>=l && t[k].r<=r){
		t[k].v.push_back(x);
		return;
	}
	int mid=(t[k].l+t[k].r)>>1;
	if(mid>=l) update(ls,l,r,x);
	if(mid<r) update(rs,l,r,x);
}

void query(int k){
	int tmp=top;
	bool flag=true;
	for(auto x:t[k].v){
		int u=find(x.u);
		int v=find(x.v);
		if(u==v){
			for(int i=t[k].l;i<=t[k].r;i++) puts("No");
			flag=false;
			break;
		}
		merge(x.u,x.v+n);
		merge(x.v,x.u+n);
	}
	if(flag){
		if(t[k].l==t[k].r){
			puts("Yes");	
			while(top>tmp){
				del(st[top--]);
			}
			return;
		}
		query(ls);
		query(rs);
	}	
	while(top>tmp){
		del(st[top--]);
	}	
}

int main(){
	n=read();m=read();k=read();
	build(1,1,k);
	for(int i=1;i<=2*n;i++){
		fa[i]=i;
		sz[i]=1;
	}
	int u,v,l,r;
	for(int i=1;i<=m;i++){
		u=read();v=read();
		l=read()+1;r=read();
		E[i].u=u;
		E[i].v=v;
		enode t={u,v};
		update(1,l,r,t);
	}
	query(1);
	return 0;
} 

线段树合并

#include<bits/stdc++.h>
#define MAXN 100005
#define mod 998244353
#define look_memory cerr<<abs(&M2-&M1)/1024.0/1024<<'\n'
#define look_time cerr<<(clock()-Time)*1.0/CLOCKS_PER_SEC<<'\n'
using namespace std;

inline int read(){
    int x=0;
    int f=1;
    char c=getchar();
    while(c<'0' || c>'9'){
    	if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0' && c<='9'){
        x=(x<<1)+(x<<3)+(c^48);
        c=getchar();
    }
    return x*f;
}

bool M1;
int n,m;
vector<int> edge[MAXN];
int fa[MAXN][25],dep[MAXN];
int rt[MAXN];
int ans[MAXN];
const int N=100000;

void dfs0(int x,int f){
	dep[x]=dep[f]+1;
	fa[x][0]=f;
	for(auto y:edge[x]){
		if(y==f) continue;
		dfs0(y,x);
	}
}

void init(){
	for(int j=1;j<=21;j++){
		for(int i=1;i<=n;i++){
			fa[i][j]=fa[fa[i][j-1]][j-1];
		}
	}
}

int LCA(int a,int b){
	if(dep[a]<dep[b]) swap(a,b);
	int step=dep[a]-dep[b];
	for(int i=0;i<=20;i++){
		if(step&(1<<i)) a=fa[a][i];
	} 
	if(a==b) return a;
	for(int i=20;i>=0;i--){
		if(fa[a][i]!=fa[b][i]){
			a=fa[a][i];
			b=fa[b][i];
		}
	}
	return fa[a][0];
}

struct segment_tree{
	struct node{
		int lc,rc;
		int val,ty;
	}t[MAXN*80];
	int tot;
	#define ls t[k].lc
	#define rs t[k].rc
	void pushup(int k){
		if(t[ls].val>=t[rs].val){
			t[k].val=t[ls].val;
			t[k].ty=t[ls].ty;
		}else{
			t[k].val=t[rs].val;
			t[k].ty=t[rs].ty;
		}
		if(!t[k].val) t[k].ty=0;
	}
	void update(int &k,int l,int r,int p,int v){
		if(!k) k=++tot;
		if(l==r){
			t[k].val+=v;
			t[k].ty=l;
			return;
		}
		int mid=(l+r)>>1;
		if(mid>=p) update(ls,l,mid,p,v);
		else update(rs,mid+1,r,p,v);
		pushup(k);
	}
	int merge(int x,int y,int l,int r){
		if(!x) return y;
		if(!y) return x;
		if(l==r){
			t[x].val+=t[y].val;
			t[x].ty=l;
			return x;
		}
		int mid=(l+r)>>1;
		t[x].lc=merge(t[x].lc,t[y].lc,l,mid);
		t[x].rc=merge(t[x].rc,t[y].rc,mid+1,r);
		pushup(x);
		return x;
	}
}ST;

void dfs(int x,int f){
	for(auto y:edge[x]){
		if(y==f) continue;
		dfs(y,x);
		rt[x]=ST.merge(rt[x],rt[y],1,N);
	}
	ans[x]=ST.t[rt[x]].ty;
}

bool M2;

signed main(){
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	int Time=clock();
	n=read();m=read();
	int u,v;
	for(int i=1;i<n;i++){
		u=read();v=read();
		edge[u].push_back(v);
		edge[v].push_back(u);
	}
	dfs0(1,0);
	init();
	int w;
	for(int i=1;i<=m;i++){
		u=read();v=read();w=read();
		int lca=LCA(u,v);
		ST.update(rt[u],1,N,w,1);
		ST.update(rt[v],1,N,w,1);
		ST.update(rt[lca],1,N,w,-1);
		if(fa[lca][0]) ST.update(rt[fa[lca][0]],1,N,w,-1);
	}
	dfs(1,0);
	for(int i=1;i<=n;i++){
		printf("%d\n",ans[i]);
	}
	look_memory;
	look_time;
	return 0;
}

线段树分裂

#include<bits/stdc++.h>
#define MAXN 200005
#define mod 998244353
#define ls t[k].lc
#define rs t[k].rc
#define look_memory cerr<<abs(&M2-&M1)/1024.0/1024<<'\n'
#define look_time cerr<<(clock()-Time)*1.0/CLOCKS_PER_SEC<<'\n'
using namespace std;

inline int read(){
    int x=0;
    int f=1;
    char c=getchar();
    while(c<'0' || c>'9'){
    	if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0' && c<='9'){
        x=(x<<1)+(x<<3)+(c^48);
        c=getchar();
    }
    return x*f;
}

bool M1;
int n,m;
struct node{
	int lc,rc;
	long long val;
}t[MAXN*40];
int rt[MAXN],tot,rcnt;
int bn[MAXN*5],dcnt;

int get_new(){
	if(dcnt) return bn[dcnt--];
	else return ++tot;
}

void del(int k){
	ls=rs=t[k].val=0;
	bn[++dcnt]=k;
}

void pushup(int k){
	t[k].val=t[ls].val+t[rs].val;
}

void update(int &k,int l,int r,int p,int v){
	if(!k) k=get_new(); 
	if(l==r){
		t[k].val+=v;
		return;
	}
	int mid=(l+r)>>1;
	if(mid>=p) update(ls,l,mid,p,v);
	else update(rs,mid+1,r,p,v);
	pushup(k);
}

void split(int k,int &x,int &y,int l,int r,int L,int R){
	if(!k) return;
	if(l>=L && r<=R){
		y=x;
		x=0;
		return;
	}
	y=get_new();
	int mid=(l+r)>>1;
	if(mid>=L) split(ls,t[x].lc,t[y].lc,l,mid,L,R);
	if(mid<R) split(rs,t[x].rc,t[y].rc,mid+1,r,L,R);
	pushup(x);
	pushup(y);
}

void merge(int &x,int y){
	if(!x || !y){
		x=x+y;
		return;
	}
	t[x].val+=t[y].val;
	merge(t[x].lc,t[y].lc);
	merge(t[x].rc,t[y].rc);
	del(y);
}

long long query(int k,int l,int r,int L,int R){
	if(l>=L && r<=R){
		return t[k].val;
	}
	int mid=(l+r)>>1;
	long long res=0;
	if(mid>=L) res+=query(ls,l,mid,L,R);
	if(mid<R) res+=query(rs,mid+1,r,L,R);
	return res; 
}

int ask_kth(int k,int l,int r,int num){
	if(l==r) return l;
	int mid=(l+r)>>1;
	if(t[ls].val>=num) return ask_kth(ls,l,mid,num);
	else return ask_kth(rs,mid+1,r,num-t[ls].val);
}

bool M2;

signed main(){
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	int Time=clock();
	n=read();m=read();
	rcnt=1;
	int x;
	for(int i=1;i<=n;i++){
		x=read();
		update(rt[1],1,n,i,x);
	}
	int op,id,y;
	while(m--){
		op=read();
		if(op==0){
			id=read();
			x=read();y=read();
			split(rt[id],rt[id],rt[++rcnt],1,n,x,y);
		}else if(op==1){
			x=read();y=read();
			merge(rt[x],rt[y]);
		}else if(op==2){
			id=read();
			x=read();y=read();
			update(rt[id],1,n,y,x);
		}else if(op==3){
			id=read();
			x=read();y=read();
			printf("%lld\n",query(rt[id],1,n,x,y));
		}else{
			id=read();x=read();
			if(t[rt[id]].val<x){
				puts("-1");
				continue;
			}
			printf("%d\n",ask_kth(rt[id],1,n,x));
		} 
	}
	look_memory;
	look_time;
	return 0;
}

离线算法

整体二分

#include<bits/stdc++.h>
#define MAXN 600005
#define inf 1000000000
using namespace std;

inline long long read(){
	long long x=0;
	char c=getchar();
	while(c<'0' || c>'9'){
		c=getchar();
	}
	while(c>='0' && c<='9'){
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return x;
}

int n,m,k;
long long c[MAXN];
vector<int> edge[MAXN];
struct node1{
	int l,r;
	long long val;
}a[MAXN];
struct node2{
	long long nd;
	int id;
}p[MAXN],tmp[MAXN];
int ans[MAXN];

int lowbit(int x){
	return x&(-x);
}

void update(int x,long long v){
	while(x<=2*m){
		c[x]+=v;
		x+=lowbit(x);
	}
}

long long query(int x){
	long long res=0;
	while(x){
		res+=c[x];
		x-=lowbit(x);
	}
	return res;
}

void whole_bny(int l,int r,int ql,int qr){
	if(qr<ql) return;
	if(l==r){
		for(int i=ql;i<=qr;i++){
			ans[p[i].id]=l;
		}
		return;
	}
	int mid=(l+r)>>1;
	for(int i=l;i<=mid;i++){
		update(a[i].l,a[i].val);
		update(a[i].r+1,-a[i].val);
	}
	int cnt1=0,cnt2=n;
	for(int i=ql;i<=qr;i++){
		long long sum=0;
		for(auto y:edge[p[i].id]){
			sum+=query(y)+query(y+m);
			if(sum>p[i].nd) break;
		}
		if(sum>=p[i].nd){
			tmp[++cnt1]=p[i]; 
		}else{
			tmp[++cnt2]=p[i];
			tmp[cnt2].nd-=sum;
		}
	}
	for(int i=l;i<=mid;i++){
		update(a[i].l,-a[i].val);
		update(a[i].r+1,a[i].val);
	}
	for(int i=1;i<=cnt1;i++){
		p[ql+i-1]=tmp[i]; 
	}
	for(int i=n+1;i<=cnt2;i++){
		p[ql+cnt1+i-n-1]=tmp[i];
	}
	whole_bny(l,mid,ql,ql+cnt1-1);
	whole_bny(mid+1,r,ql+cnt1,qr);
}
 
int main(){
	n=read();m=read();
	int o;
	for(int i=1;i<=m;i++){
		o=read();
		edge[o].push_back(i);
	}
	for(int i=1;i<=n;i++){
		p[i].nd=read();
		p[i].id=i;
	}
	k=read();
	for(int i=1;i<=k;i++){
		a[i].l=read();
		a[i].r=read();
		a[i].val=read();
		if(a[i].r<a[i].l) a[i].r+=m;
	}
	whole_bny(1,k+1,1,n);
	for(int i=1;i<=n;i++){
		if(ans[i]>k){
			puts("NIE");
		}else{
			printf("%d\n",ans[i]);
		}
	}
	return 0;
}

CDQ分治

#include<bits/stdc++.h>
#define MAXN 100005
#define MAXK 200005
using namespace std;

inline int read(){
	int x=0;
	char c=0;
	while(c<'0' || c>'9'){
		c=getchar();
	}
	while(c>='0' && c<='9'){
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return x;
}

int n,nn,k;
struct node{
	int x,y,z;
	int res,cnt;
}b[MAXN],a[MAXN],t[MAXN];
int c[MAXK];
int ans[MAXK];

bool cmp1(node aa,node bb){
	if(aa.x==bb.x){
		if(aa.y==bb.y) return aa.z<bb.z;
		return aa.y<bb.y;
	}
	return aa.x<bb.x;
}

bool cmp2(node aa,node bb){
	if(aa.y==bb.y) return aa.z<bb.z;
	return aa.y<bb.y;
}

int lowbit(int x){
	return x&(-x);
}

void add(int x,int v){
	while(x<=k){
		c[x]+=v;
		x+=lowbit(x);
	}
	return;
}

int query(int x){
	int res=0;
	while(x){
		res+=c[x];
		x-=lowbit(x);
	}
	return res;
}

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;
	for(;j<=r;j++){
		while(i<=mid && a[i].y<=a[j].y){
			add(a[i].z,a[i].cnt);
			i++;
		}
		a[j].res+=query(a[j].z);
	}
	i=l,j=mid+1;
	for(;j<=r;j++){
		while(i<=mid && a[i].y<=a[j].y){
			add(a[i].z,-a[i].cnt);
			i++;
		}
	}
	inplace_merge(a+l,a+mid+1,a+r+1,cmp2);
}

int main(){
	n=read();k=read();
	for(int i=1;i<=n;i++){
		b[i].x=read();
		b[i].y=read();
		b[i].z=read();
	}
	sort(b+1,b+1+n,cmp1);
	int tmp=0;
	for(int i=1;i<=n;i++){
		tmp++;
		if(b[i].x!=b[i+1].x || b[i].y!=b[i+1].y || b[i].z!=b[i+1].z){
			a[++nn]=b[i];
			a[nn].cnt=tmp;
			tmp=0;
		}
	}
	swap(n,nn);
	CDQ(1,n);
	for(int i=1;i<=n;i++){
		ans[a[i].res+a[i].cnt-1]+=a[i].cnt;
	}
	for(int i=0;i<nn;i++){
		printf("%d\n",ans[i]);
	}
	return 0;
}

莫队

#include<bits/stdc++.h>
#define MAXN 50005
using namespace std;

inline int read(){
	int x=0;
	char c=getchar();
	while(c<'0' || c>'9'){
		c=getchar();
	}
	while(c>='0' && c<='9'){
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return x;
}

int n,m;
int c[MAXN],cnt[MAXN];
struct node{
	int id;
	int l,r;
}q[MAXN];
int pos[MAXN],len;
struct node2{
	long long p,q;
}ans[MAXN];
long long sum;//ƽ·½ºÍ

bool cmp(node aa,node bb){
	if(pos[aa.l]==pos[bb.l]) return aa.r<bb.r;
	return aa.l<bb.l;
}

long long gcd(long long aa,long long bb){
	if(bb==0) return aa;
	return gcd(bb,aa%bb);
}

void add(int x){
	sum+=cnt[x];
	cnt[x]++;
}

void del(int x){
	cnt[x]--;
	sum-=cnt[x];
}

void solve(){
	for(int i=1,l=1,r=0;i<=m;i++){
		while(l>q[i].l) add(c[--l]);
		while(r<q[i].r) add(c[++r]);
		while(l<q[i].l) del(c[l++]);
		while(r>q[i].r) del(c[r--]);
		if(q[i].l==q[i].r){
			ans[q[i].id].p=0;
			ans[q[i].id].q=1;
			continue;
		}
		ans[q[i].id].p=sum;
		ans[q[i].id].q=(long long)(r-l+1)*(r-l)/2;
	}
}

int main(){
	n=read();m=read();
	for(int i=1;i<=n;i++){
		c[i]=read();
	}
	for(int i=1;i<=m;i++){
		q[i].l=read();
		q[i].r=read();
		q[i].id=i;
	}
	len=sqrt(n);
	for(int i=1;i<=n;i++){
		pos[i]=(i-1)/len+1;
	}
	sort(q+1,q+1+m,cmp);
	solve();
	for(int i=1;i<=m;i++){
		int g=gcd(ans[i].p,ans[i].q);
		if(g){
			ans[i].p/=g;
			ans[i].q/=g;
		}
		printf("%d/%d\n",ans[i].p,ans[i].q);
	}
	return 0;
}

回滚莫队

#include<bits/stdc++.h>
#define MAXN 200005
using namespace std;

inline long long read(){
	long long x=0;
	char c=getchar();
	while(c<'0' || c>'9'){
		c=getchar();
	}
	while(c>='0' && c<='9'){
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return x;
}

int n,m;
int a[MAXN];
struct node{
	int l,r;
	int id;
}q[MAXN];
int pos[MAXN],len;
int lsh[MAXN],nn;
int bg[MAXN],ed[MAXN],ed2[MAXN];
int res1,res2;
int ans[MAXN];

bool cmp(node aa,node bb){
	if(pos[aa.l]==pos[bb.l]) return aa.r<bb.r;
	return aa.l<bb.l;
}

void solve(){
	int block=0,nowb=0,l=0,r=0;
	for(int i=1;i<=m;i++){
		if(pos[q[i].l]==pos[q[i].r]){
			for(int j=q[i].l;j<=q[i].r;j++){
				bg[a[j]]=0;
			}
			res1=0;
			for(int j=q[i].l;j<=q[i].r;j++){
				if(!bg[a[j]]) bg[a[j]]=j;
				res1=max(res1,j-bg[a[j]]);
			}
			ans[q[i].id]=res1;
			for(int j=q[i].l;j<=q[i].r;j++){
				bg[a[j]]=0;
			}
			res1=0;
			continue;
		}
		nowb=pos[q[i].l];
		if(block!=nowb){
			res1=0;
			for(int j=l;j<=r;j++){
				bg[a[j]]=ed[a[j]]=0;
			}
			l=min(n,nowb*len);
			r=l-1;
			block=nowb;
		}
		while(r<q[i].r){
			r++;
			if(!bg[a[r]]) bg[a[r]]=r;
			ed[a[r]]=r;
			res1=max(res1,r-bg[a[r]]);
		}
		int t=l,res2=0;
		while(t>q[i].l){
			t--;
			if(!ed2[a[t]]) ed2[a[t]]=t;
			res2=max(res2,max(ed[a[t]],ed2[a[t]])-t);
		}
		while(t<l){
			ed2[a[t]]=0;
			t++;
		}
		ans[q[i].id]=max(res1,res2);
	}
}

int main(){
	//freopen("P5906.in","r",stdin);
	//freopen("P5906.out","w",stdout);
	n=read();
	for(int i=1;i<=n;i++){
		a[i]=read();
		lsh[i]=a[i];
	}
	sort(lsh+1,lsh+1+n);
	nn=unique(lsh+1,lsh+1+n)-lsh-1;
	for(int i=1;i<=n;i++){
		a[i]=lower_bound(lsh+1,lsh+1+nn,a[i])-lsh;
	}
	m=read();
	for(int i=1;i<=m;i++){
		q[i].l=read();
		q[i].r=read();
		q[i].id=i;
	}
	len=sqrt(n);
	for(int i=1;i<=n;i++){
		pos[i]=(i-1)/len+1;
	}
	sort(q+1,q+1+m,cmp);
	
	solve();
	for(int i=1;i<=m;i++){
		printf("%d\n",ans[i]);
	}		
	return 0;
}

带修莫队

#include<bits/stdc++.h>
#define MAXN 200005
using namespace std;

inline long long read(){
	long long x=0;
	char c=getchar();
	while(c<'0' || c>'9'){
		c=getchar();
	}
	while(c>='0' && c<='9'){
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return x;
}

int n,m;
int a[MAXN];
int cntq,cntp;
struct node{
	int l,r,t;
	int id;
}q[MAXN]; 
struct node1{
	int x,y;
}p[MAXN];
int cnt[1000005];
int pos[MAXN],len;
int ans[MAXN],res;

bool cmp(node aa,node bb){
	if(pos[aa.l]==pos[bb.l]){
		if(pos[aa.r]==pos[bb.r]) return aa.t<bb.t;
		return aa.r<bb.r;
	} 
	return aa.l<bb.l;
}

void add(int x){
	if(!cnt[x]) res++;
	cnt[x]++;
}

void del(int x){
	cnt[x]--;
	if(!cnt[x]) res--;
}

void upd(int id,int x){
	if(q[id].l<=p[x].x && q[id].r>=p[x].x){
		del(a[p[x].x]);
		add(p[x].y);
	}
	swap(a[p[x].x],p[x].y);
}

void solve(){
	int l=1,r=0,t=0;
	for(int i=1;i<=cntq;i++){
		while(l>q[i].l) add(a[--l]);
		while(l<q[i].l) del(a[l++]);
		while(r>q[i].r) del(a[r--]);
		while(r<q[i].r) add(a[++r]);
		while(t<q[i].t) upd(i,++t);
		while(t>q[i].t) upd(i,t--);
		ans[q[i].id]=res;
	}
}

int main(){
	n=read();m=read(); 
	for(int i=1;i<=n;i++){
		a[i]=read();
	}
	char op[5];
	for(int i=1;i<=m;i++){
		scanf("%s",op);
		if(op[0]=='Q'){
			cntq++;
			q[cntq].l=read();q[cntq].r=read();
			q[cntq].t=cntp;q[cntq].id=cntq;
		}else{
			cntp++;
			p[cntp].x=read();p[cntp].y=read();
		}
	}
	
	len=pow(n,0.666);
	for(int i=1;i<=n;i++){
		pos[i]=(i-1)/len+1;
	}
	sort(q+1,q+1+cntq,cmp);
	solve();
	for(int i=1;i<=cntq;i++){
		printf("%d\n",ans[i]);
	}
	return 0;
}
  • 二离莫队

图论

最短路 SPFA dijkstra

int n,m,s;
struct node{
	int to,val;
	bool operator < (node tmp) const{
		return tmp.val<val;
	}
};
vector<node> edge[MAXN];
priority_queue<node> q;
bool vis[MAXN];
int dis[MAXN];

void dijkstra(){
	memset(dis,0x3f,sizeof(dis));
	dis[s]=0;
	q.push((node){s,0});
	while(!q.empty()){
		node tmp=q.top();
		q.pop();
		int u=tmp.to;
		if(vis[u]) continue;
		vis[u]=true;
		for(int i=0;i<edge[u].size();i++){
			int v=edge[u][i].to;
			int w=edge[u][i].val;
			if(dis[v]>dis[u]+w){
				dis[v]=dis[u]+w;
				q.push((node){v,dis[v]});
			}
		}
	}
}
int n,m,s;
struct node{
	int to,val;
};
vector<node> edge[MAXN];
queue<int> q;
bool vis[MAXN];
int dis[MAXN];

void SPFA(){
	for(int i=1;i<=n;i++){
		dis[i]=inf;
	}
	dis[s]=0;
	q.push(s);
	vis[s]=true;
	while(!q.empty()){
		int u=q.front();
		q.pop();
		vis[u]=false;
		for(int i=0;i<edge[u].size();i++){
			int v=edge[u][i].to;
			int w=edge[u][i].val;
			if(dis[v]>dis[u]+w){
				dis[v]=dis[u]+w;
				if(!vis[v]){
					q.push(v);
					vis[v]=true;
				} 
			}
		}
	}
}

最小生成树

拓扑排序

差分约束

tarjan

缩点

int n,m;
vector<int> edge[MAXN];
int dfn[MAXN],low[MAXN],tot;
int belong[MAXN],bcnt;
stack<int> st;
bool inst[MAXN];

void tarjan(int x){
	dfn[x]=low[x]=++tot;
	st.push(x);
	inst[x]=true;
	for(int i=0;i<edge[x].size();i++){
		int y=edge[x][i];
		if(!dfn[y]){
			tarjan(y);
			low[x]=min(low[x],low[y]);
		}else if(inst[y]){
			low[x]=min(low[x],dfn[y]);
		}
	}
	if(dfn[x]==low[x]){
		int k;
		bcnt++;
		do{
			k=st.top();
			st.pop();
			belong[k]=bcnt;
			inst[k]=false;
		}while(k!=x);
	}
}

割点

 #include<bits/stdc++.h>
#define MAXN 20005
using namespace std;

inline int read(){
	int x=0;
	char c=0;
	while(c<'0' || c>'9'){
		c=getchar();
	}
	while(c>='0' && c<='9'){
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return x;
}

int n,m;
vector<int> edge[MAXN];
int dfn[MAXN],low[MAXN],tot;
int buc[MAXN],cnt;
int root;

void tarjan(int x){
	dfn[x]=low[x]=++tot;
	int son=0;
	for(int i=0;i<edge[x].size();i++){
		int y=edge[x][i];
		if(!dfn[y]){
			son++;
			tarjan(y);
			low[x]=min(low[x],low[y]);
			if(low[y]>=dfn[x] && x!=root){
				if(!buc[x]){
					++cnt;
					buc[x]=true;
				} 
			}
		}else{
			low[x]=min(low[x],dfn[y]);
		}
	}
	if(x==root && son>1){
		++cnt;
		buc[x]=true;
	}
	return;
}

int main(){
	n=read();m=read();
	int u,v;
	for(int i=1;i<=m;i++){
		u=read();v=read();
		edge[u].push_back(v);
		edge[v].push_back(u);
	}	
	for(int i=1;i<=n;i++){
		if(!dfn[i]){
			root=i;
			tarjan(i);
		}
	}	
	printf("%d\n",cnt);
	for(int i=1;i<=n;i++){
		if(buc[i]) printf("%d ",i);
	}	
	return 0;
} 

割边

点双

#include<bits/stdc++.h>
#define MAXN 500005
using namespace std;

inline int read(){
	int x=0;
	char c=0;
	while(c<'0' || c>'9'){
		c=getchar();
	}
	while(c>='0' && c<='9'){
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return x;
}

int n,m;
vector<int> edge[MAXN];
int dfn[MAXN],low[MAXN],tot;
stack<int> st;
int bcc;
vector<int> ans[MAXN];

void tarjan(int x,int f){
	dfn[x]=low[x]=++tot;
	st.push(x);
	int son=0;
	for(int i=0;i<edge[x].size();i++){
		int y=edge[x][i];
		if(!dfn[y]){
			son++;
			tarjan(y,x);
			low[x]=min(low[x],low[y]);
			if(low[y]>=dfn[x]){
				int k;
				bcc++;
				do{
					k=st.top();
					st.pop();
					ans[bcc].push_back(k);
				}while(k!=y);
				ans[bcc].push_back(x);
			}
		}else{
			low[x]=min(low[x],dfn[y]);
		}
	}
	if(f==0 && son==0) ans[++bcc].push_back(x);
	return;
}

int main(){
	n=read();m=read();
	int u,v;
	for(int i=1;i<=m;i++){
		u=read();v=read();
		edge[u].push_back(v);
		edge[v].push_back(u);
	}
	for(int i=1;i<=n;i++){
		if(!dfn[i]) tarjan(i,0);
	}
	printf("%d\n",bcc);
	for(int i=1;i<=bcc;i++){
		printf("%d ",ans[i].size());
		for(int j=0;j<ans[i].size();j++){
			printf("%d ",ans[i][j]);
		}
		puts("");
	}
	return 0;
}

边双

#include<bits/stdc++.h>
#define MAXN 500005
using namespace std;

inline int read(){
	int x=0;
	char c=0;
	while(c<'0' || c>'9'){
		c=getchar();
	}
	while(c>='0' && c<='9'){
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return x;
}

int n,m;
struct node{
	int to,id;
};
vector<node> edge[MAXN];
int dfn[MAXN],low[MAXN],tot;
vector<int> ans[MAXN];
int belong[MAXN],bcnt;
stack<int> st;

void tarjan(int x,int fe){
	dfn[x]=low[x]=++tot;
	st.push(x);
	for(int i=0;i<edge[x].size();i++){
		int y=edge[x][i].to;
		int e=edge[x][i].id;
		if(e==(fe^1)) continue;
		if(!dfn[y]){
			tarjan(y,e);
			low[x]=min(low[x],low[y]);
		}else{
			low[x]=min(low[x],dfn[y]);
		}
	}
	if(dfn[x]==low[x]){
		bcnt++;
		int k;
		do{
			k=st.top();
			st.pop();
			belong[k]=bcnt;
			ans[bcnt].push_back(k);
		}while(k!=x);
	}
}

int main(){
	n=read();m=read();
	int u,v;
	for(int i=1;i<=m;i++){
		u=read();v=read();
		edge[u].push_back((node){v,i<<1});
		edge[v].push_back((node){u,i<<1|1});
	}
	for(int i=1;i<=n;i++){
		if(!dfn[i]) tarjan(i,0);
	}
	printf("%d\n",bcnt);
	for(int i=1;i<=bcnt;i++){
		printf("%d ",ans[i].size());
		for(int j=0;j<ans[i].size();j++){
			printf("%d ",ans[i][j]);
		}
		puts("");
	}
	return 0;
}

二分图最大匹配

#include<bits/stdc++.h>
#define MAXN 1005
using namespace std;

inline int read(){
	int x=0;
	char c=getchar();
	while(c<'0' || c>'9'){
		c=getchar();
	}
	while(c>='0' && c<='9'){
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return x;
}

int n,m,e;
vector<int> edge[MAXN];
int ans;
bool vis[MAXN<<1];
int f[MAXN<<1];

bool sp(int x){
	for(int i=0;i<edge[x].size();i++){
		int y=edge[x][i];
		if(!vis[y]){
			vis[y]=true;
			if(!f[y] || sp(f[y])){
				f[y]=x;
				return true;
			}
		}
	}
	return false;
}

void match(){
	for(int i=1;i<=n;i++){
		memset(vis,0,sizeof(vis));
		if(sp(i)){
			ans++;
		}
	}
}

int main(){
	//freopen("","r",stdin);
	//freopen("","w",stdout);
	n=read();m=read();e=read();
	int u,v;
	for(int i=1;i<=e;i++){
		u=read();v=read();
		edge[u].push_back(v);
	}
	match();
	printf("%d",ans);
	return 0;
}

2-SAT

#include<bits/stdc++.h>
#define MAXN 2000005
#define mod 1000000007
using namespace std;

inline int read(){
	int x=0;
	char c=0;
	while(c<'0' || c>'9'){
		c=getchar();
	}
	while(c>='0' && c<='9'){
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return x;
}

int n,m;
vector<int> edge[MAXN];
int dfn[MAXN],low[MAXN],tot;
int belong[MAXN],bcnt;
stack<int> st;
bool inst[MAXN];

void tarjan(int x){
	dfn[x]=low[x]=++tot;
	st.push(x);
	inst[x]=true;
	for(int i=0;i<edge[x].size();i++){
		int y=edge[x][i];
		if(!dfn[y]){
			tarjan(y);
			low[x]=min(low[x],low[y]);
		}else if(inst[y]){
			low[x]=min(low[x],dfn[y]);
		}
	}
	if(dfn[x]==low[x]){
		bcnt++;
		int k;
		do{
			k=st.top();
			st.pop();
			inst[k]=false;
			belong[k]=bcnt;
		}while(k!=x);
	}
}

int main(){
	n=read();m=read();
	int u,v,a,b;
	for(int i=1;i<=m;i++){
		u=read();a=read();
		v=read();b=read();
		u--;v--;
		edge[(u<<1)+!a].push_back((v<<1)+b);
		edge[(v<<1)+!b].push_back((u<<1)+a);
	}
	
	for(int i=0;i<(n<<1);i++){
		if(!dfn[i]) tarjan(i);
	}
	for(int i=0;i<(n<<1);i+=2){
		if(belong[i]==belong[i+1]){
			puts("IMPOSSIBLE");
			return 0;
		}
	}
	puts("POSSIBLE");
	for(int i=0;i<(n<<1);i+=2){
		if(belong[i]<belong[i+1]){
			printf("0 ");
		}else{
			printf("1 ");
		}
	}
	return 0;
} 

圆方树

仙人掌建树

#include<bits/stdc++.h>
#define MAXN 100005
using namespace std;

inline int read(){
    int x=0;
    char c=getchar();
    while(c<'0' || c>'9'){
        c=getchar();
    }
    while(c>='0' && c<='9'){
        x=(x<<1)+(x<<3)+(c^48);
        c=getchar();
    }
    return x;
}

int n,m,q;
int sum[MAXN<<1];
int cnt;

struct round_sqare_tree{
	struct node{
		int to,val;
	};
	vector<node> edge[MAXN<<1];
	int fa[MAXN<<1][25],dep[MAXN<<1],dis[MAXN<<1];
	void add(int u,int v,int w){
		edge[u].push_back((node){v,w});
	}
	void dfs(int x,int ff){
		fa[x][0]=ff;
		dep[x]=dep[ff]+1;
		for(auto tmp:edge[x]){
			int y=tmp.to;
			int w=tmp.val;
			if(y==ff) continue;
			dis[y]=dis[x]+w;
			dfs(y,x);
		}
	}
	void init(){
		for(int j=1;j<=21;j++){
			for(int i=1;i<=cnt;i++){
				fa[i][j]=fa[fa[i][j-1]][j-1];
			}
		}
	}
	int get_dis(int x,int y){
		if(dep[x]<dep[y]) swap(x,y);
		int a=x,b=y;
		int step=dep[a]-dep[b];
		for(int i=0;i<=20;i++){
			if(step&(1<<i)) a=fa[a][i];
		}
		if(a==b){
			return dis[x]-dis[y];
		}
		for(int i=20;i>=0;i--){
			if(fa[a][i]!=fa[b][i]){
				a=fa[a][i];
				b=fa[b][i];
			}
		}		
		int lca=fa[a][0];
		if(lca>n){
			return dis[x]+dis[y]-dis[a]-dis[b]+min(abs(sum[a]-sum[b]),sum[lca]-abs(sum[a]-sum[b]));
		}else{
			return dis[x]+dis[y]-2*dis[lca];
		}
	}
}RST;

struct cactus{
	struct node{
		int to,val;
	};
	vector<node> edge[MAXN];
	int dfn[MAXN],low[MAXN],tot;
	int fa[MAXN],vl[MAXN];
	void add(int u,int v,int w){
		edge[u].push_back((node){v,w});
	}
	void solve(int t,int s,int w){
		cnt++;
		int p=s,sm=w;
		while(p!=fa[t]){
			sum[p]=sm;
			sm+=vl[p];
			p=fa[p];
		}
		sum[cnt]=sum[t];
		sum[t]=0;	
		p=s;
		while(p!=fa[t]){
			int mn=min(sum[p],sum[cnt]-sum[p]);
			RST.add(p,cnt,mn);
			RST.add(cnt,p,mn);
			p=fa[p];
		}
	}
	void tarjan(int x,int ff){
		dfn[x]=low[x]=++tot;
		for(auto tmp:edge[x]){
			int y=tmp.to;
			int w=tmp.val;
			if(y==ff) continue;
			if(!dfn[y]){
				fa[y]=x;
				vl[y]=w;
				tarjan(y,x);
				low[x]=min(low[x],low[y]);
			}else{
				low[x]=min(low[x],dfn[y]);
			}
			if(low[y]<=dfn[x]) continue;//是割点,则子树内有点双
			RST.add(x,y,w);
			RST.add(y,x,w);
		}
		for(auto tmp:edge[x]){
			int y=tmp.to;
			if(fa[y]!=x && dfn[y]>dfn[x]) solve(x,y,tmp.val);
		}
	}
}CC;

int main(){
	n=read();m=read();q=read();
	int u,v,w;
	for(int i=1;i<=m;i++){
		u=read();v=read();w=read();
		CC.add(u,v,w);
		CC.add(v,u,w);
	}
	cnt=n;
	CC.tarjan(1,0);
	RST.dfs(1,0);
	RST.init();
	while(q--){
		u=read();v=read();
		int ans=RST.get_dis(u,v);
		printf("%d\n",ans);
	}
	return 0;
}

点双建树

#include<bits/stdc++.h>
#define MAXN 500005
using namespace std;

inline int read(){
    int x=0;
    char c=getchar();
    while(c<'0' || c>'9'){
        c=getchar();
    }
    while(c>='0' && c<='9'){
        x=(x<<1)+(x<<3)+(c^48);
        c=getchar();
    }
    return x;
}

int n,m,q;
int w[MAXN<<1];
int cnt;

struct round_sqare_tree{
	vector<int> edge[MAXN<<1];
	int fa[MAXN<<1][25],dep[MAXN<<1],dis[MAXN<<1];
	void add(int u,int v){
		edge[u].push_back(v);
	}
	void dfs(int x,int ff){
		fa[x][0]=ff;
		dep[x]=dep[ff]+1;
		dis[x]=dis[ff]+w[x];
		for(auto y:edge[x]){
			if(y==ff) continue;
			dfs(y,x);
		}
	}
	void init(){
		for(int j=1;j<=21;j++){
			for(int i=1;i<=cnt;i++){
				fa[i][j]=fa[fa[i][j-1]][j-1];
			}
		}
	}
	int LCA(int a,int b){
		if(dep[a]<dep[b]) swap(a,b);
		int step=dep[a]-dep[b];
		for(int i=0;i<=20;i++){
			if(step&(1<<i)) a=fa[a][i];
		}
		if(a==b) return a;
		for(int i=20;i>=0;i--){
			if(fa[a][i]!=fa[b][i]){
				a=fa[a][i];
				b=fa[b][i];
			}
		}		
		return fa[a][0];
	}
	int get_dis(int x,int y){
		int lca=LCA(x,y);
		return dis[x]+dis[y]-dis[lca]-dis[fa[lca][0]];
	}
}RST;

struct cactus{
	vector<int> edge[MAXN];
	int dfn[MAXN],low[MAXN],tot;
	stack<int> st;
	void add(int u,int v){
		edge[u].push_back(v);
	}
	void solve(int x,int y){
		cnt++;
		int k;
		do{
			k=st.top();
			st.pop();
			RST.add(cnt,k);
			RST.add(k,cnt);
		}while(k!=y);		
		RST.add(cnt,x);
		RST.add(x,cnt);
	}
	void tarjan(int x,int ff){
		dfn[x]=low[x]=++tot;
		st.push(x);
		for(auto y:edge[x]){
			if(!dfn[y]){
				tarjan(y,x);
				low[x]=min(low[x],low[y]);
				if(low[y]>=dfn[x]) solve(x,y);
			}else{
				low[x]=min(low[x],dfn[y]);
			}
		}
	}
}CC;

int main(){
	n=read();m=read();
	int u,v;
	for(int i=1;i<=m;i++){
		u=read();v=read();
		CC.add(u,v);
		CC.add(v,u);
	}
	for(int i=1;i<=n;i++) w[i]=1;
	cnt=n;
	CC.tarjan(1,0);
	RST.dfs(1,0);
	RST.init();
	q=read();
	while(q--){
		u=read();v=read();
		int ans=RST.get_dis(u,v);
		printf("%d\n",ans);
	}
	return 0;
}

网络流

最大流

#include<bits/stdc++.h>
#define MAXN 205
#define MAXM 5005
using namespace std;

inline int read(){
	int x=0;
	char c=getchar();
	while(c<'0' || c>'9'){
		c=getchar();
	}
	while(c>='0' && c<='9'){
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return x;
}

int n,m,s,t;
struct node{
	int to,val,nxt;
}E[MAXM<<1];
int cnt=1;
int head[MAXN],now[MAXN];
long long ans;
int dis[MAXN];
queue<int> q;
const int inf=0x3f3f3f3f3f3f3f3f;

void add(int u,int v,int w){
	cnt++;
	E[cnt].to=v;
	E[cnt].val=w;
	E[cnt].nxt=head[u];
	head[u]=cnt;
}

bool bfs(){
	memset(dis,0x3f,sizeof(dis));
	while(!q.empty()) q.pop();
	q.push(s);
	dis[s]=0;
	now[s]=head[s];
	while(!q.empty()){
		int x=q.front();
		q.pop();
		for(int i=head[x];i;i=E[i].nxt){
			int y=E[i].to;
			int w=E[i].val;
			if(w>0 && dis[y]==inf){
				q.push(y);
				now[y]=head[y];
				dis[y]=dis[x]+1;
				if(y==t) return true;
			}
		}
	}
	return false;
}

long long dfs(int x,int mn){
	if(x==t) return mn;
	long long res=0;
	for(int i=now[x];i && mn;i=E[i].nxt){
		int y=E[i].to;
		int w=E[i].val;
		now[x]=i;
		if(w>0 &&  dis[y]==dis[x]+1){
			long long t=dfs(y,min(mn,w));
			if(!t) dis[y]=inf;
			E[i].val-=t;
			E[i^1].val+=t;
			res+=t;
			mn-=t;
		}
	}
	return res;
}

void Dinic(){
	while(bfs()){
		ans+=dfs(s,inf);
	}
}

int main(){
	//freopen("","r",stdin);
	//freopen("","w",stdout);
	n=read();m=read();
	s=read();t=read();
	int u,v,w;
	for(int i=1;i<=m;i++){
		u=read();v=read();w=read();
		add(u,v,w);
		add(v,u,0);
	}
	Dinic();
	printf("%lld",ans);
	return 0;
}

费用流

#include<bits/stdc++.h>
#define MAXN 5005
#define MAXM 50005
#define look_memory cerr<<abs(&M2-&M1)/1024.0/1024<<'\n'
#define look_time cerr<<(clock()-Time)*1.0/CLOCKS_PER_SEC<<'\n'
using namespace std;

inline int read(){
    int x=0;
    int f=1;
    char c=getchar();
    while(c<'0' || c>'9'){
    	if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0' && c<='9'){
        x=(x<<1)+(x<<3)+(c^48);
        c=getchar();
    }
    return x*f;
}

bool M1;
int n,m;
int s,t;
int head[MAXN],to[MAXM<<1],nxt[MAXM<<1],val[MAXM<<1],cst[MAXM<<1],cnt=1;
int dis[MAXN],f[MAXN],pre[MAXN];
bool vis[MAXN];
queue<int> q;
int ans,ansc;
const int inf=1e9;
bool M2;

void add(int u,int v,int w,int c){
	cnt++;
	to[cnt]=v;
	nxt[cnt]=head[u];
	head[u]=cnt;
	val[cnt]=w;
	cst[cnt]=c;
}

bool SPFA(){
	memset(dis,0x3f,sizeof(dis));
	memset(vis,0,sizeof(vis));
	while(!q.empty()) q.pop();
	q.push(s);
	vis[s]=1;
	dis[s]=0;
	f[s]=inf;
	f[t]=0;
	while(!q.empty()){
		int x=q.front();
		q.pop();
		vis[x]=0;
		for(int i=head[x];i;i=nxt[i]){
			int y=to[i];
			int w=val[i];
			int c=cst[i];
			if(!w || dis[y]<=dis[x]+c) continue;
			dis[y]=dis[x]+c;
			f[y]=min(f[x],w);
			pre[y]=i;
			if(!vis[y]){
				q.push(y);
				vis[y]=1;
			}
		}
	}
	if(f[t]) return true;
	else return false;
}

void update(){
	ans+=f[t];
	for(int x=t;x!=s;x=to[pre[x]^1]){
		val[pre[x]]-=f[t];
		val[pre[x]^1]+=f[t];
		ansc+=f[t]*cst[pre[x]];
	}
}

void EK(){
	while(SPFA()){
		update();
	}
}

int main(){
//	freopen("","r",stdin);
//	freopen("","w",stdout);
	int Time=clock();
	n=read();m=read();
	s=read();t=read();
	int u,v,w,c;
	for(int i=1;i<=m;i++){
		u=read();v=read();w=read();c=read();
		add(u,v,w,c);
		add(v,u,0,-c);
	}
	EK();
	printf("%d %d",ans,ansc);
	return 0;
}

树论

LCA

int n,m,s;
vector<int> edge[MAXN];
int fa[MAXN][25],dep[MAXN];

void dfs(int x,int f){
	fa[x][0]=f;
	dep[x]=dep[f]+1;
	for(int i=0;i<edge[x].size();i++){
		int y=edge[x][i];
		if(y==f) continue;
		dfs(y,x);
	}
}

void init(){
	for(int j=1;j<=21;j++){
		for(int i=1;i<=n;i++){
			fa[i][j]=fa[fa[i][j-1]][j-1];
		}
	}
}

int LCA(int a,int b){
	if(dep[a]<dep[b]) swap(a,b);
	int step=dep[a]-dep[b];
	for(int i=0;i<=20;i++){
		if(step&(1<<i)){
			a=fa[a][i];
		}
	}
	if(a==b) return a;
	for(int i=20;i>=0;i--){
		if(fa[a][i]!=fa[b][i]){
			a=fa[a][i];
			b=fa[b][i];
		}
	}
	return fa[a][0];
}

树的重心

int n;
int sz[MAXN],wt[MAXN];
int root;
vector<int> edge[MAXN];

void dfs(int x,int f){
	sz[x]=1;
	wt[x]=0;
	for(int i=0;i<edge[x].size();i++){
		int y=edge[x][i];
		if(y==f) continue;
		dfs(y,x);
		sz[x]+=sz[y];
		wt[x]=max(wt[x],sz[y]);
	}
	wt[x]=max(wt[x],n-sz[x]);
	if(wt[x]<wt[root]){
		root=x;
	}
}

树的直径

#include<bits/stdc++.h>
#define MAXN 105
using namespace std;

inline int read(){
	int x=0;
	char c=getchar();
	while(c<'0' || c>'9'){
		c=getchar();
	}
	while(c>='0' && c<='9'){
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return x;
}

int n,m;
struct node{
	int to,val;
};
vector<node> edge[MAXN];
long long dis[MAXN];
int s,e;

void dfs(int x,int f){
	for(int i=0;i<edge[x].size();i++){
		int y=edge[x][i].to;
		int w=edge[x][i].val;
		if(y==f) continue;
		dis[y]=dis[x]+w;
		if(dis[y]>dis[e]){
			e=y;
		}
		dfs(y,x);
	}
}

int main(){
	//freopen("","r",stdin);
	//freopen("","w",stdout);
	n=read();m=read();
	int u,v,w;
	for(int i=1;i<=m;i++){
		u=read();v=read();w=read();
		edge[u].push_back((node){v,w});
		edge[v].push_back((node){u,w});
	}
	dfs(1,0);
	memset(dis,0,sizeof(dis));
	s=e;
	e=0;
	dfs(s,0);
	printf("%d %d\n",s,e);
	return 0;
}

树链剖分

#include<bits/stdc++.h>
#define MAXN 100005
#define int long long
#define look_memory cerr<<abs(&M2-&M1)/1024.0/1024<<'\n'
#define look_time cerr<<(clock()-Time)*1.0/CLOCKS_PER_SEC<<'\n'
using namespace std;

inline int read(){
    int x=0;
    int f=1;
    char c=getchar();
    while(c<'0' || c>'9'){
    	if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0' && c<='9'){
        x=(x<<1)+(x<<3)+(c^48);
        c=getchar();
    }
    return x*f;
}

bool M1;
int n,m,rt,mod;
vector<int> edge[MAXN];
int a[MAXN],w[MAXN];
int fa[MAXN],dep[MAXN],sz[MAXN],son[MAXN],top[MAXN],dfn[MAXN],tot;

void dfs1(int x,int f){
	fa[x]=f;
	dep[x]=dep[f]+1;
	sz[x]=1;
	for(auto y:edge[x]){
		if(y==f) continue;
		dfs1(y,x);
		sz[x]+=sz[y];
		if(sz[y]>sz[son[x]]) son[x]=y;
	} 
}

void dfs2(int x,int f,int tp){
	top[x]=tp;
	dfn[x]=++tot;
	w[tot]=a[x];
	if(son[x]) dfs2(son[x],x,tp);
	for(auto y:edge[x]){
		if(y==f || y==son[x]) continue;
		dfs2(y,x,y);
	}
}

struct segment_tree{
	#define ls k<<1
	#define rs k<<1|1
	struct node{
		int l,r;
		int sum,tag;
	}t[MAXN<<2];
	void pushup(int k){
		t[k].sum=(t[ls].sum+t[rs].sum)%mod;
	}
	void pushtag(int k,int v){
		(t[k].sum+=v*(t[k].r-t[k].l+1))%=mod;
		(t[k].tag+=v)%=mod;
	}
	void pushdown(int k){
		if(t[k].tag){
			pushtag(ls,t[k].tag);
			pushtag(rs,t[k].tag);
			t[k].tag=0;
		}
	}
	void build(int k,int l,int r){
		t[k].l=l;t[k].r=r;
		if(l==r){
			t[k].sum=w[l]%mod;
			return;
		}
		int mid=(l+r)>>1;
		build(ls,l,mid);
		build(rs,mid+1,r);
		pushup(k);
	}
	void update(int k,int l,int r,int v){
		if(t[k].l>=l && t[k].r<=r){
			pushtag(k,v);
			return;
		}
		pushdown(k);
		int mid=(t[k].l+t[k].r)>>1;
		if(mid>=l) update(ls,l,r,v);
		if(mid<r) update(rs,l,r,v);
		pushup(k);
	}
	int query(int k,int l,int r){
		if(t[k].l>=l && t[k].r<=r){
			return t[k].sum;
		}
		pushdown(k);
		int mid=(t[k].l+t[k].r)>>1;
		int res=0;
		if(mid>=l) res=(res+query(ls,l,r))%mod;
		if(mid<r) res=(res+query(rs,l,r))%mod;
		return res;
	}
}ST;

void update(int a,int b,int v){
	while(top[a]!=top[b]){
		if(dep[top[a]]<dep[top[b]]) swap(a,b);
		ST.update(1,dfn[top[a]],dfn[a],v);
		a=fa[top[a]];
	}
	if(dep[a]>dep[b]) swap(a,b);
	ST.update(1,dfn[a],dfn[b],v);
}

int query(int a,int b){
	int res=0;
	while(top[a]!=top[b]){
		if(dep[top[a]]<dep[top[b]]) swap(a,b);
		(res+=ST.query(1,dfn[top[a]],dfn[a]))%=mod;
		a=fa[top[a]];
	}
	if(dep[a]>dep[b]) swap(a,b);
	(res+=ST.query(1,dfn[a],dfn[b]))%=mod;
	return res;
}

void upd(int x,int v){
	ST.update(1,dfn[x],dfn[x]+sz[x]-1,v);
}

int qry(int x){
	return ST.query(1,dfn[x],dfn[x]+sz[x]-1);
}

bool M2;

signed main(){
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	int Time=clock();
	n=read();m=read();
	rt=read();mod=read();
	for(int i=1;i<=n;i++){
		a[i]=read();
	}
	int u,v;
	for(int i=1;i<n;i++){
		u=read();v=read();
		edge[u].push_back(v);
		edge[v].push_back(u);
	}
	dfs1(rt,0);
	dfs2(rt,0,rt);
	ST.build(1,1,n);
	int op,x,y;
	while(m--){
		op=read();
		if(op==1){
			x=read();y=read();v=read();
			update(x,y,v);
		}else if(op==2){
			x=read();y=read();
			printf("%lld\n",query(x,y));
		}else if(op==3){
			x=read();v=read();
			upd(x,v);
		}else{
			x=read();
			printf("%lld\n",qry(x));
		}
	}
	look_memory;
	look_time;
	return 0;
}

长链剖分

k级祖先

#include<bits/stdc++.h>
#define MAXN 500005
using namespace std;

inline int read(){
    int x=0;
    char c=getchar();
    while(c<'0' || c>'9'){
        c=getchar();
    }
    while(c>='0' && c<='9'){
        x=(x<<1)+(x<<3)+(c^48);
        c=getchar();
    }
    return x;
}

#define ui unsigned int
ui s;
inline ui get(ui x) {
	x ^= x << 13;
	x ^= x >> 17;
	x ^= x << 5;
	return s = x; 
}

int n,q;
vector<int> edge[MAXN];
int fa[MAXN][25],dep[MAXN],len[MAXN],son[MAXN],top[MAXN];
long long Ans;
int lg[MAXN];
vector<int> U[MAXN],D[MAXN];

void dfs1(int x,int f){
	fa[x][0]=f;
	dep[x]=dep[f]+1;
	for(auto y:edge[x]){
		if(y==f) continue;
		dfs1(y,x);
		if(len[y]>len[son[x]]) son[x]=y;
	}
	len[x]=len[son[x]]+1;
}

void dfs2(int x,int f,int tp){
	top[x]=tp;
	if(x==tp){
		int now=x;
		U[x].resize(len[x]+10);
		D[x].resize(len[x]+10);
		for(int i=0;i<len[x];i++){
			U[x][i]=now;
			now=fa[now][0];
		}
		now=x;
		for(int i=0;i<len[x];i++){
			D[x][i]=now;
			now=son[now];
		}
	}
	if(son[x]) dfs2(son[x],x,tp);
	for(auto y:edge[x]){
		if(y==f || y==son[x]) continue;
		dfs2(y,x,y);
	} 
}

void init(){
	lg[1]=0;
	for(int i=2;i<=n;i++){
		lg[i]=lg[i>>1]+1;
	}
	for(int j=1;j<=21;j++){
		for(int i=1;i<=n;i++){
			fa[i][j]=fa[fa[i][j-1]][j-1];
		}
	}
}

int get_kth(int x,int k){
	if(!k) return x;
	x=fa[x][lg[k]];
	k-=1<<lg[k];
	k-=dep[x]-dep[top[x]];
	x=top[x];
	if(k>=0) return U[x][k];
	else return D[x][-k];
} 

int main(){
	n=read();q=read();
	scanf("%u",&s);
	int f,rt;
	for(int i=1;i<=n;i++){
		f=read();
		if(!f){
			rt=i;
		}
		edge[f].push_back(i);
		edge[i].push_back(f);
	}
	dfs1(rt,0);
	dfs2(rt,0,rt);
	init();
	int ans=0;
	int x,k;
	for(int i=1;i<=q;i++){
		x=((get(s)^ans)%n)+1;
		k=(get(s)^ans)%dep[x];
		ans=get_kth(x,k);
		Ans^=1ll*ans*i;
	}
	printf("%lld",Ans);
	return 0;
}

长剖优化DP

#include<bits/stdc++.h>
#define MAXN 100005
using namespace std;

inline int read(){
    int x=0;
    char c=getchar();
    while(c<'0' || c>'9'){
        c=getchar();
    }
    while(c>='0' && c<='9'){
        x=(x<<1)+(x<<3)+(c^48);
        c=getchar();
    }
    return x;
}

int n;
vector<int> edge[MAXN];
int dep[MAXN],len[MAXN],son[MAXN];
long long *f[MAXN],*g[MAXN];
long long base[MAXN<<2],*p=base;
long long ans;

void dfs1(int x,int ff){
	dep[x]=dep[ff]+1;
	for(auto y:edge[x]){
		if(y==ff) continue;
		dfs1(y,x);
		if(len[y]>len[son[x]]) son[x]=y;
	} 
	len[x]=len[son[x]]+1;
}

void dfs(int x,int ff){
	if(son[x]){
		f[son[x]]=f[x]+1;
		g[son[x]]=g[x]-1;
		dfs(son[x],x);
	}
	ans+=g[x][0];
	f[x][0]=1;
	for(auto y:edge[x]){
		if(y==ff || y==son[x]) continue;
		f[y]=p;
		p+=len[y]<<1;
		g[y]=p;
		p+=len[y]<<1;
		dfs(y,x);
		for(int i=0;i<len[y];i++){
			if(i) ans+=f[x][i-1]*g[y][i];
			ans+=g[x][i+1]*f[y][i];	
		}
		for(int i=0;i<len[y];i++){
			g[x][i+1]+=f[x][i+1]*f[y][i];
			if(i) g[x][i-1]+=g[y][i];
		}
		for(int i=0;i<len[y];i++){
			f[x][i+1]+=f[y][i];
		}
	} 
}

int main(){
	n=read();
	int u,v;
	for(int i=1;i<n;i++){
		u=read();v=read();
		edge[u].push_back(v);
		edge[v].push_back(u);
	}
	dfs1(1,0);
	f[1]=p;
	p+=len[1]<<1;
	g[1]=p;
	p+=len[1]<<1;
	dfs(1,0);
	printf("%lld",ans);
	return 0;
}

DSU On Tree

#include<bits/stdc++.h>
#define MAXN 100005
using namespace std;

inline int read(){
    int x=0;
    int f=1;
    char c=getchar();
    while(c<'0' || c>'9'){
    	if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0' && c<='9'){
        x=(x<<1)+(x<<3)+(c^48);
        c=getchar();
    }
    return x*f;
}

int n,m;
vector<int> edge[MAXN];
int c[MAXN],cnt;
bool mark[MAXN];
int dep[MAXN],sz[MAXN],son[MAXN];
int ans[MAXN];

void dfs(int x,int f){
	dep[x]=dep[f]+1;
	sz[x]=1;
	son[x]=0;
	for(auto y:edge[x]){
		if(y==f) continue;
		dfs(y,x);
		sz[x]+=sz[y];
		if(sz[y]>sz[son[x]]){
			son[x]=y;
		}
	}
}

void clear(int x,int f){
	mark[c[x]]=false;
	for(auto y:edge[x]){
		if(y==f) continue;
		clear(y,x);
	}
} 

void dfs2(int x,int f,int id){
	if(!mark[c[x]]){
		mark[c[x]]=true;
		cnt++;
	}
	for(auto y:edge[x]){
		if(y==f || y==son[id]) continue;
		dfs2(y,x,id);
	}
}

void dfs1(int x,int f){
	for(auto y:edge[x]){
		if(y==f || y==son[x]) continue;
		dfs1(y,x);
		clear(y,x);
		cnt=0;
	}
	if(son[x]) dfs1(son[x],x);
	dfs2(x,f,x);
	ans[x]=cnt;
}

int main(){
	n=read();
	int u,v;
	for(int i=1;i<n;i++){
		u=read();v=read();
		edge[u].push_back(v);
		edge[v].push_back(u);
	}
	for(int i=1;i<=n;i++){
		c[i]=read();
	}
	dfs(1,0);
	dfs1(1,0);
	m=read();
	int x;
	while(m--){
		x=read();
		printf("%d\n",ans[x]);
	}
	return 0;
}

DP

01背包

完全背包

多重背包

数位DP

区间DP(例题)

树形DP(例题)

换根DP(例题)

状压DP(例题)

数论

线性筛

int n,q;
int prime[10000005] ,cnt;
bool ntp[MAXN];
void xxs(){
	for(int i=2;i<=n;i++){
		if(!ntp[i]){
			prime[++cnt]=i;
		}
		for(int j=1;j<=cnt&&i*prime[j]<=n;j++){
			ntp[i*prime[j]]=true;
			if(i%prime[j]==0) break;
		}
	}
}
  • GCD
int GCD(int a,int b){
	if(b==0) return a;
	return GCD(b,a%b);
}

逆元

inv[1]=1;
for(int i=2;i<=n;i++){
	inv[i]=(p-p/i)*inv[p%i]%p;
}
mul[0]=mul[1]=1;
for(int i=2;i<=n;i++){
	mul[i]=mul[i-1]*i%p;
}
inv[n]=qpow(mul[n],p-2);
for(int i=n-1;i>=1;i--){
	inv[i]=inv[i+1]*(i+1)%p;
}

线性基

#include<bits/stdc++.h>
#define MAXN 105
#define int long long
#define look_memory cerr<<abs(&M2-&M1)/1024.0/1024<<'\n'
#define look_time cerr<<(clock()-Time)*1.0/CLOCKS_PER_SEC<<'\n'
using namespace std;

inline int read(){
    int x=0;
    int f=1;
    char c=getchar();
    while(c<'0' || c>'9'){
    	if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0' && c<='9'){
        x=(x<<1)+(x<<3)+(c^48);
        c=getchar();
    }
    return x*f;
}

bool M1;
int n;
int a[MAXN];
long long s[100];
const int logn=60;
long long ans;

bool insert(long long x){
	for(int i=logn;i>=0;i--){
		if(x&(1ll<<i)){
			if(!s[i]){
				for(int j=i;j>=0;j--){
					if(x&(1ll<<j)) x^=s[j];
				}
				s[i]=x;
				for(int j=logn;j>i;j--){
					if(s[j]&(1ll<<i)) s[j]^=s[i];
				}
				return true; 
			}else{
				x^=s[i];
			}
		}
	}
	return false;
}

long long get_max(){
	long long res=0;
	for(int i=logn;i>=0;i--){
		if(res^s[i]>res) res^=s[i];
	} 
	return res;
}

bool M2;

signed main(){
//	freopen("","r",stdin);
//	freopen("","w",stdout);
	int Time=clock();
	n=read();
	for(int i=1;i<=n;i++){
		a[i]=read();
		insert(a[i]); 
	}
	ans=get_max();	
	printf("%lld\n",ans);
	look_memory;
	look_time;
	return 0;
}

字符串

哈希

trie树

#include<bits/stdc++.h>
#define MAXN 3000006
using namespace std;

inline int read(){
	int x=0;
	char c=getchar();
	while(c<'0' || c>'9'){
		c=getchar();
	}
	while(c>='0' && c<='9'){
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return x;
}

int T;
int n,q;
int trie[MAXN][70],tot;
int cnt[MAXN];
char s[MAXN];

int get_val(char c){
	if(c>='a' && c<='z') return c-'a';
	if(c>='A' && c<='Z') return c-'A'+26;
	if(c>='0' && c<='9') return c-'0'+52;
}

void insert(char str[]){
	int len=strlen(str);
	int p=0;
	for(int i=0;i<len;i++){
		int c=get_val(str[i]);
		if(!trie[p][c]) trie[p][c]=++tot;
		p=trie[p][c];
		cnt[p]++;
	}
}

int search(char str[]){
	int len=strlen(str);
	int p=0;
	for(int i=0;i<len;i++){
		int c=get_val(str[i]);
		if(!trie[p][c]) return 0;
		p=trie[p][c];
	}
	return cnt[p];
}

int main(){
//	printf("!");
	T=read();
	while(T--){
		for(int i=0;i<=tot;i++){
			for(int j=0;j<=70;j++){
				trie[i][j]=0;
			}
			cnt[i]=0;
		}
		tot=0;
		n=read();q=read();
		for(int i=1;i<=n;i++){
			scanf("%s",s);
			insert(s);
		}
		for(int i=1;i<=q;i++){
			scanf("%s",s);
			int ans=search(s);
			printf("%d\n",ans);
		}
	}
	return 0;
}

KMP

#include<bits/stdc++.h>
#define MAXN 1000005
using namespace std;

char a[MAXN],b[MAXN];
int nxt[MAXN];

int main(){
	cin>>a+1;
	cin>>b+1;
	int la=strlen(a+1);
	int lb=strlen(b+1);
	
	int j=0;
	for(int i=2;i<=lb;i++){
		while(j && b[i]!=b[j+1]) j=nxt[j];
		if(b[i]==b[j+1]) j++;
		nxt[i]=j;
	}
	
	j=0;
	for(int i=1;i<=la;i++){
		while(j && a[i]!=b[j+1]) j=nxt[j];
		if(a[i]==b[j+1]) j++;
		if(j==lb){
			printf("%d\n",i-j+1);
		}
	}
	for(int i=1;i<=lb;i++){
		printf("%d ",nxt[i]);
	}
	return 0;
}

AC自动机

#include<bits/stdc++.h>
#define MAXN 200005
#define look_memory cerr<<abs(&M2-&M1)/1024.0/1024<<'\n'
#define look_time cerr<<(clock()-Time)*1.0/CLOCKS_PER_SEC<<'\n'
using namespace std;

inline int read(){
    int x=0;
    int f=1;
    char c=getchar();
    while(c<'0' || c>'9'){
    	if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0' && c<='9'){
        x=(x<<1)+(x<<3)+(c^48);
        c=getchar();
    }
    return x*f;
}

bool M1;
int n;
char s[MAXN*10],t[MAXN]; 
int pos[MAXN];
int ch[MAXN][30],fail[MAXN],tot;
bool ky[MAXN];
int cnt[MAXN]; 
int id[MAXN],idx;
int rt=0;
queue<int> q;

void insert(char s[],int id){
	int len=strlen(s+1); 
	int x=rt;
	for(int i=1;i<=len;i++){
		int w=s[i]-'a';
		if(!ch[x][w]) ch[x][w]=++tot;
		x=ch[x][w];
	}
	pos[id]=x;
}

void bfs(){
	for(int i=0;i<26;i++){
		if(ch[rt][i]) q.push(ch[rt][i]);
 	}
 	while(!q.empty()){
 		int x=q.front();
 		q.pop();
		id[++idx]=x;
		for(int i=0;i<26;i++){
			if(ch[x][i]){
				fail[ch[x][i]]=ch[fail[x]][i];
				q.push(ch[x][i]);
			}else{
				ch[x][i]=ch[fail[x]][i];
			}
		}	
	}
}

void query(char s[]){
	int x=rt;
	int len=strlen(s+1);
	for(int i=1;i<=len;i++){
		int w=s[i]-'a';
		x=ch[x][w];
		cnt[x]++;
	}
}

void topo(){
	for(int i=idx;i>=1;i--){
		cnt[fail[id[i]]]+=cnt[id[i]];
	}
}

bool M2;

int main(){
//	freopen("","r",stdin);
//	freopen("","w",stdout);
	int Time=clock();
	n=read();
	for(int i=1;i<=n;i++){
		scanf("%s",t+1);
		insert(t,i);
	}
	bfs();
	scanf("%s",s+1);
	query(s);
	topo();
	for(int i=1;i<=n;i++){
		printf("%d\n",cnt[pos[i]]);
	}
	return 0;
}

后缀数组(SA)

#include<bits/stdc++.h>
#define MAXN 2000050
#define look_memory cerr<<abs(&M2-&M1)/1024.0/1024<<'\n'
#define look_time cerr<<(clock()-Time)*1.0/CLOCKS_PER_SEC<<'\n'
using namespace std;

inline int read(){
    int x=0;
    int f=1;
    char c=getchar();
    while(c<'0' || c>'9'){
    	if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0' && c<='9'){
        x=(x<<1)+(x<<3)+(c^48);
        c=getchar();
    }
    return x*f;
}

bool M1;
int n,k;
char s[MAXN];
int rk[MAXN],sa[MAXN];
int hr[MAXN],hs[MAXN];
int bn[MAXN],tmp[MAXN];
bool M2;

int main(){
//	freopen("","r",stdin);
//	freopen("","w",stdout);
	int Time=clock();
	scanf("%s",s+1);
	n=strlen(s+1);
	k=max(n,255);
	for(int i=1;i<=n;i++){
		rk[i]=s[i];
		bn[rk[i]]++;
	}
	for(int i=1;i<=k;i++){
		bn[i]+=bn[i-1];
	}
	for(int i=1;i<=n;i++){
		sa[bn[rk[i]]]=i;
		bn[rk[i]]--;
	}
	for(int j=1;j<=n;j<<=1){
		int cnt=0;
		for(int i=n-j+1;i<=n;i++){
			tmp[++cnt]=i;
		}
		for(int i=1;i<=n;i++){
			if(sa[i]-j>0) tmp[++cnt]=sa[i]-j;
		}
		for(int i=1;i<=k;i++){
			bn[i]=0;
		}
		for(int i=1;i<=n;i++){
			bn[rk[i]]++;
		}
		for(int i=1;i<=k;i++){
			bn[i]+=bn[i-1]; 
		}
		for(int i=n;i>=1;i--){
			sa[bn[rk[tmp[i]]]]=tmp[i];
			bn[rk[tmp[i]]]--;
		}
		tmp[sa[1]]=1;
		for(int i=2;i<=n;i++){
			int t=(rk[sa[i]]!=rk[sa[i-1]]) | (rk[sa[i]+j]!=rk[sa[i-1]+j]);
			tmp[sa[i]]=tmp[sa[i-1]]+t;
		}
		for(int i=1;i<=n;i++){
			rk[i]=tmp[i];
		}
		if(rk[sa[n]]==n) break;
	}
	for(int i=1;i<=n;i++){
		printf("%d ",sa[i]);
	}puts("");
	look_memory;
	look_time;
	return 0;
}

后缀自动机(SAM)

#include<bits/stdc++.h>
#define MAXN 2000005
#define look_memory cerr<<abs(&M2-&M1)/1024.0/1024<<'\n'
#define look_time cerr<<(clock()-Time)*1.0/CLOCKS_PER_SEC<<'\n'
using namespace std;

inline int read(){
    int x=0;
    int f=1;
    char c=getchar();
    while(c<'0' || c>'9'){
    	if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0' && c<='9'){
        x=(x<<1)+(x<<3)+(c^48);
        c=getchar();
    }
    return x*f;
}

bool M1;
int n;
char s[MAXN];
long long ans;
int fa[MAXN],ch[MAXN][27],sz[MAXN],mx[MAXN],lst,tot;
int bn[MAXN],topo[MAXN];

void push(int x){
	int p=lst,np=++tot;
	lst=np;
	mx[np]=mx[p]+1;
	sz[np]=1;
	while(p && !ch[p][x]){
		ch[p][x]=np;
		p=fa[p];
	}
	if(!p) fa[np]=1;
	else{
		int q=ch[p][x];
		if(mx[q]==mx[p]+1) fa[np]=q;
		else{
			int nq=++tot;
			mx[nq]=mx[p]+1;
			memcpy(ch[nq],ch[q],sizeof(ch[q]));
			fa[nq]=fa[q];
			fa[q]=fa[np]=nq;
			while(ch[p][x]==q){
				ch[p][x]=nq;
				p=fa[p];
			}
		}
	}
}

void build(){
	tot=lst=1;
	for(int i=1;i<=n;i++){
		push(s[i]-'a');
	}
	for(int i=1;i<=tot;i++){
		bn[mx[i]]++;
	}
	for(int i=1;i<=n;i++){
		bn[i]+=bn[i-1];
	}
	for(int i=1;i<=tot;i++){
		topo[bn[mx[i]]--]=i;
	}
	for(int i=tot;i>=1;i--){
		sz[fa[topo[i]]]+=sz[topo[i]];
	}
}

void solve(){
	for(int i=1;i<=tot;i++){
		if(sz[i]>1){
			ans=max(ans,1ll*sz[i]*mx[i]);
		}
	}
}

bool M2;

signed main(){
//	freopen("","r",stdin);
//	freopen("","w",stdout);
	int Time=clock();
	scanf("%s",s+1);
	n=strlen(s+1);
	build();
	solve();
	printf("%lld\n",ans);
	look_memory;
	look_time;
	return 0;
}
posted @ 2025-04-22 14:40  洛苡hh  阅读(3)  评论(0)    收藏  举报