代码康复训练

树状数组区间求和P3374

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=5e5+10;
int n,m;
struct BIT
{
    int lim,tre[N];
    inline int lowbit(int x){return x&(-x);}
    inline void insert(int x,int val){for(int i=x;i<=lim;i+=lowbit(i))tre[i]+=val;}
    inline int query(int x){int temp=0;for(int i=x;i>0;i-=lowbit(i))temp+=tre[i];return temp;}
    inline int query(int l,int r){return query(r)-query(l-1);}
}T;
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    return x*f;
}
#undef int
int main()
{
    #define  int long long
    T.lim=n=read(); m=read();
    for(int i=1,x;i<=n;i++) x=read(),T.insert(i,x);
    for(int i=1,opt,x,y;i<=m;i++)
    {
        opt=read(); x=read(); y=read();
        if(opt==1) T.insert(x,y);
        else printf("%lld\n",T.query(x,y));
    }
    return 0;
}

树状数组区间加P3368

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=5e5+10;
int n,m;
struct BIT
{
    int lim,tre[N];
    inline int lowbit(int x){return x&(-x);}
    inline void insert(int x,int val){for(int i=x;i<=lim;i+=lowbit(i))tre[i]+=val;}
    inline void insert(int l,int r,int val){insert(l,val);insert(r+1,-val);}
    inline int query(int x){int temp=0;for(int i=x;i>0;i-=lowbit(i))temp+=tre[i];return temp;}
}T;
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    return x*f;
}
#undef int
int main()
{
    #define  int long long
    T.lim=n=read(); m=read();
    for(int i=1,x;i<=n;i++) x=read(),T.insert(i,i,x);
    for(int i=1,opt,x,y,k;i<=m;i++)
    {
        opt=read(); x=read();
        if(opt==1) y=read(),k=read(),T.insert(x,y,k);
        else printf("%lld\n",T.query(x));
    }
    return 0;
}

线段树区间加P3372

#include<bits/stdc++.h>
#define int long long
#define f() cout<<"Test"<<endl;
#define ls x<<1
#define rs x<<1|1
using namespace std;
inline int read()
{
	int x=0,f=1; char ch=getchar();
	while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
const int N=1e5+10;
struct BIT
{
	int tre[N],lim;
	inline int lowbit(int x){return x&(-x);}
	inline int query(int x){int sum=0;for(int i=x;i;i-=lowbit(i))sum+=tre[i];return sum;}
	inline void insert(int x,int val){for(int i=x;i<=lim;i+=lowbit(i))tre[i]+=val;}
	inline int query(int l,int r){return query(r)-query(l-1);}
};
struct Segment_Tree
{
	struct Node
	{
		int dat,laz;
	}tre[N<<2];
	inline void push_up(int x){tre[x].dat=tre[ls].dat+tre[rs].dat;}
	inline void push_down(int x,int l,int r)
	{
		if(!tre[x].laz) return ;
		int mid=(l+r)>>1;
		tre[ls].dat+=tre[x].laz*(mid-l+1);
		tre[rs].dat+=tre[x].laz*(r-mid);
		tre[ls].laz+=tre[x].laz;
		tre[rs].laz+=tre[x].laz;
		tre[x].laz=0;
	}
	inline void insert(int x,int l,int r,int L,int R,int val)
	{
		if(L<=l&&r<=R)
		{
			tre[x].dat+=val*(r-l+1);
			tre[x].laz+=val; return ;
		}
		int mid=(l+r)>>1; push_down(x,l,r);
		if(L<=mid) insert(ls,l,mid,L,R,val);
		if(R>mid) insert(rs,mid+1,r,L,R,val);
		push_up(x);
	} 
	inline int query(int x,int l,int r,int L,int R)
	{
		if(L<=l&&r<=R) return tre[x].dat;
		int mid=(l+r)>>1,sum=0;
		push_down(x,l,r);
		if(L<=mid) sum+=query(ls,l,mid,L,R);
		if(R>mid) sum+=query(rs,mid+1,r,L,R);
		push_up(x);
		return sum;
	}
}T;
int n,m;
#undef int
int main()
{
	#define int long long
	n=read(); m=read();
	for(int i=1,dat;i<=n;i++)
		dat=read(),T.insert(1,1,n,i,i,dat);
	for(int i=1,opt,x,y,k;i<=m;i++)
	{
		opt=read(); x=read(); y=read();
		if(opt==1) k=read(),T.insert(1,1,n,x,y,k);
		else printf("%lld\n",T.query(1,1,n,x,y));
	}
    return 0;
}

主席树P3834

#include<bits/stdc++.h>
#define int long long
#define f() cout<<"Test"<<endl;
#define ls tre[x].l
#define rs tre[x].r
using namespace std;
inline int read()
{
	int x=0,f=1; char ch=getchar();
	while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
const int N=2e5+10;
int n,m,cnt,all,root[N],s[N],lsh[N];
struct Node
{
	int dat,l,r;
}tre[N*20];
void push_up(int x){tre[x].dat=tre[ls].dat+tre[rs].dat;}
int insert(int pre,int l,int r,int pos)
{
	int mid=(l+r)>>1,x=++all; tre[x]=tre[pre];
	if(l==r) return tre[x].dat++,x;
	if(pos<=mid) ls=insert(tre[pre].l,l,mid,pos);
	else rs=insert(tre[pre].r,mid+1,r,pos);
	push_up(x); return x;
}
int query(int x,int y,int l,int r,int k)
{
	if(l==r) return l;
	int lsum=tre[tre[y].l].dat-tre[ls].dat,mid=(l+r)>>1;
	if(lsum>=k) return query(ls,tre[y].l,l,mid,k);
	return query(rs,tre[y].r,mid+1,r,k-lsum);
}
#undef int
int main()
{
	#define int long long
	n=read(); m=read();
	for(int i=1;i<=n;i++)
		s[i]=lsh[i]=read();
	sort(lsh+1,lsh+n+1);
	cnt=unique(lsh+1,lsh+n+1)-lsh-1;
	root[0]=++all;
	for(int i=1;i<=n;i++)
		s[i]=lower_bound(lsh+1,lsh+cnt+1,s[i])-lsh,
		root[i]=insert(root[i-1],1,cnt,s[i]);
	for(int i=1,l,r,k;i<=m;i++)
	{
		l=read(); r=read(); k=read();
		printf("%lld\n",lsh[query(root[l-1],root[r],1,cnt,k)]);
	}
    return 0;
}

KMP

#include<bits/stdc++.h>
#define int long long
#define f() cout<<"Test"<<endl;
using namespace std;
inline int read()
{
	int x=0,f=1; char ch=getchar();
	while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
const int N=1e6+10;
int n,m,nxt[N];
char s1[N],s2[N];
#undef int
int main()
{
	#define int long long
    scanf("%s%s",s1+1,s2+1);
    n=strlen(s1+1); m=strlen(s2+1);
    for(int i=2,j=0;i<=m;i++)
    {
    	while(j&&s2[j+1]!=s2[i]) j=nxt[j];
    	j+=(s2[j+1]==s2[i]); nxt[i]=j;
	}
	for(int i=1,j=0;i<=n;i++)
	{
		while(j&&s1[i]!=s2[j+1]) j=nxt[j];
		j+=(s2[j+1]==s1[i]);
		if(j==m) printf("%lld\n",i-m+1);
	}
	for(int i=1;i<=m;i++) printf("%lld ",nxt[i]);
	return 0;
}

分块 (P3202 弹飞绵羊)

#include<bits/stdc++.h>
#define int long long
#define f() cout<<"Test"<<endl;
using namespace std;
inline int read()
{
	int x=0,f=1; char ch=getchar();
	while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
const int N=2e5+10;
int n,cnt,T,pos[N],l[N],r[N],s[N],nxt[N],f[N];
#undef int
inline void deal(int x)
{
	for(int i=r[x];i>=l[x];i--)
		if(i+s[i]>r[x]) f[i]=1,nxt[i]=i+s[i];
		else f[i]=f[i+s[i]]+1,nxt[i]=nxt[i+s[i]];
}
inline int solve(int x){int ans=0;while(x<=n) ans+=f[x],x=nxt[x]; return ans;}
int main()
{
	#define int long long
    n=read();
    for(int i=1;i<=n;i++) s[i]=read();
	for(int i=1;i<=sqrt(n);i++) l[i]=(i-1)*sqrt(n)+1,r[i]=i*sqrt(n);
	if(r[cnt=sqrt(n)]!=n) l[cnt+1]=r[cnt]+1,r[++cnt]=n;
	for(int i=1;i<=cnt;i++) for(int j=l[i];j<=r[i];j++) pos[j]=i;
	for(int i=1;i<=cnt;i++) deal(i); 
	T=read();
	while(T--)
	{
		int opt,p,num; opt=read(); p=read()+1;
		if(opt==1) printf("%lld\n",solve(p));
		else num=read(),s[p]=num,deal(pos[p]);
	}
	return 0;
}

AC自动机+拓扑优化 LuoguP5357

#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"Test: "<<endl
using namespace std;
inline int read()
{
	int x=0,f=1; char ch=getchar();
	while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
const int N=2e6+10,M=2e5+10;
int n,cnt=1,du[N],ans[M];
int tot,head[M],nxt[M],ver[M];
char ch[N];
queue<int> q;
vector<int> v[N];
void add_edge(int x,int y)
{
	ver[++tot]=y; nxt[tot]=head[x];
	head[x]=tot; du[y]++;
}
struct Trie
{
	struct Node
	{
		int son[26],fail,dat;
	}tre[N];
	int New(int &x){if(!x) return x=++cnt; return x;}
	void insert(char *s,int id)
	{
		int len=strlen(s),pos=1;
		for(int i=0;i<len;i++)
			pos=New(tre[pos].son[s[i]-'a']);
		v[pos].push_back(id);
	}
	void get_Fail()
	{
		for(int i=0;i<26;i++) tre[0].son[i]=1;
		q.push(1); 
		while(!q.empty())
		{
			int x=q.front(); q.pop();
			for(int i=0;i<26;i++)
			{
				int fail=tre[x].fail,to=tre[x].son[i];
				if(!to) tre[x].son[i]=tre[fail].son[i]; 
				else
				{
					tre[to].fail=tre[fail].son[i];
					add_edge(to,tre[fail].son[i]);
					q.push(to);
				}
			}
		}
	}
	void topu()
	{
		for(int i=1;i<=cnt;i++)
			if(!du[i]) q.push(i);
		while(!q.empty())
		{
			int x=q.front(); q.pop();
			for(int i=head[x];i;i=nxt[i])
			{
				int to=ver[i];
				tre[to].dat+=tre[x].dat;
				if(!(--du[to])) q.push(to);
			}
		}
	}
	void query(char *s)
	{
		int len=strlen(s),pos=1;
		for(int i=0;i<len;i++)
		{
			pos=tre[pos].son[s[i]-'a'];
			tre[pos].dat++;
		}
		topu();
	}
}T;
#undef int
int main()
{
	#define int long long
	n=read();
	for(int i=1;i<=n;i++)
		scanf("%s",ch),T.insert(ch,i);
	scanf("%s",ch); T.get_Fail(); T.query(ch);
	for(int i=1;i<=cnt;i++)
		for(int j=0;j<v[i].size();j++)
			ans[v[i][j]]=T.tre[i].dat;
	for(int i=1;i<=n;i++) printf("%lld\n",ans[i]);
	return 0;
}

普通平衡树P3369

Splay

#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"Test: "<<endl
using namespace std;
inline int read()
{
	int x=0,f=1; char ch=getchar();
	while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
const int N=1e5+10;
struct Splay
{
	int cnt,root,fa[N],dat[N],rec[N],siz[N],son[N][2];
	void clear(int x){fa[x]=dat[x]=rec[x]=siz[x]=son[x][0]=son[x][1]=0;} 
	int get(int x){return son[fa[x]][1]==x;}
	void push_up(int x)
	{
		if(!x) return ;
		siz[x]=rec[x];
		if(son[x][0]) siz[x]+=siz[son[x][0]];
		if(son[x][1]) siz[x]+=siz[son[x][1]]; 
	}
	void connect(int x,int y,int pos)
	{
		if(x) fa[x]=y;
		if(y) son[y][pos]=x;
	}
	void rotate(int x)
	{
		int f=fa[x],ff=fa[fa[x]],px=get(x),pf=get(f);
		connect(son[x][px^1],f,px);
		connect(f,x,px^1);
		connect(x,ff,pf);
		push_up(f); push_up(x);
	}
	void splay(int x)
	{
		for(int f;f=fa[x];rotate(x))
			if(fa[f]) rotate(get(x)==get(f)?f:x);
		root=x;
	}
	void insert(int val)
	{
		if(!root)
		{
			root=++cnt; dat[root]=val;
			siz[root]=rec[root]=1;
			son[root][0]=son[root][1]=0;
			return ;
		}
		int x=root,f=0;
		while(true)
		{
//			cout<<"Test\n";
			if(dat[x]==val)
			{
			//	cout<<x<<endl;
				rec[x]++;
				push_up(x); push_up(f);
				splay(x); return ;
			}
			f=x; x=son[x][val>dat[x]];
			if(x) continue;
			dat[++cnt]=val;
			siz[cnt]=rec[cnt]=1;
			fa[cnt]=f; son[f][val>dat[f]]=cnt;
			push_up(f); splay(cnt); return ;
		}
	}
	int find(int val)//查排名 
	{
		int x=root,temp=0;
		while(true)
		{
		//	if(x) cout<<x<<' '<<val<<' '<<dat[x]<<' '<<rec[x]<<endl;
			if(val<dat[x]){x=son[x][0];continue;}
			temp+=siz[son[x][0]];
			if(val==dat[x]) return splay(x),temp+1;
			temp+=rec[x]; x=son[x][1];
		}
	}
	int kth(int rk)
	{
		int x=root;
		while(true)
		{
			if(son[x][0]&&rk<=siz[son[x][0]]){x=son[x][0]; continue;}
			if(son[x][0]) rk-=siz[son[x][0]];
			if(rk<=rec[x]) return splay(x),dat[x];
			rk-=rec[x]; x=son[x][1]; 
		}
	}
	int ask_pre()
	{
		int x=son[root][0];
		while(son[x][1]) x=son[x][1];
		return x;
	}
	int ask_suf()
	{
		int x=son[root][1];
		while(son[x][0]) x=son[x][0];
		return x;
	}
	void del(int val)
	{
		find(val);
		if(rec[root]>1) return rec[root]--,push_up(root),void();
		if(!son[root][0]&&!son[root][1]) return clear(root),root=0,void();
		if(!son[root][0])
		{
			int temp=root;
			fa[root=son[root][1]]=0;
			clear(temp); return ;
		}
		if(!son[root][1])
		{
			int temp=root;
			fa[root=son[root][0]]=0;
			clear(temp); return ;
		}
		int temp=root,left=ask_pre();
		splay(left); connect(son[temp][1],root,1);
		clear(temp); push_up(root);
	}
}T;
int n;
#undef int
int main()
{
	#define int long long
	n=read();
	for(int i=1,opt,x;i<=n;i++)
	{
		opt=read(); x=read();
		if(opt==1) T.insert(x);
		else if(opt==2) T.del(x);
		else if(opt==3) T.insert(x),printf("%lld\n",T.find(x)),T.del(x);
		else if(opt==4) printf("%lld\n",T.kth(x));
		else if(opt==5) T.insert(x),printf("%lld\n",T.dat[T.ask_pre()]),T.del(x);
		else T.insert(x),printf("%lld\n",T.dat[T.ask_suf()]),T.del(x);
	}
	return 0;
}

FHQ-Treap

#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"Test: "<<endl
#define ls tre[x].l
#define rs tre[x].r
using namespace std;
inline int read()
{
	int x=0,f=1; char ch=getchar();
	while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
const int N=1e5+10;
struct FHQ_Treap
{
	int all,root;
	struct Node
	{
		int l,r,siz,dat,key;
	}tre[N];
	int New(int val)
	{
		tre[++all]=(Node){0,0,1,val,rand()};
		return all;
	}
	void push_up(int x){tre[x].siz=tre[ls].siz+tre[rs].siz+1;}
	void split(int x,int val,int &u,int &v)
	{
		if(!x) return u=v=0,void();
		if(tre[x].dat<=val) u=x,split(rs,val,rs,v);
		else v=x,split(ls,val,u,ls);
		push_up(x);
	}
	int merge(int x,int y)//保证x的值都小于y 
	{
		if(!x||!y) return x+y;
		if(tre[x].key>tre[y].key)
			return tre[x].r=merge(tre[x].r,y),push_up(x),x;
		return tre[y].l=merge(x,tre[y].l),push_up(y),y;
	}
	void insert(int val)
	{
		int x=0,y=0; split(root,val,x,y);
		root=merge(merge(x,New(val)),y);
	}
	void del(int val)
	{
		int x=0,y=0,z=0;
		split(root,val,x,z);
		split(x,val-1,x,y);
		y=merge(tre[y].l,tre[y].r);
		root=merge(merge(x,y),z);
	}
	int find(int val)
	{
		int x=0,y=0;
		split(root,val-1,x,y);
		int temp=tre[x].siz+1;
		root=merge(x,y);
		return temp;
	}
	int kth(int x,int rk)
	{
		if(tre[ls].siz+1==rk) return tre[x].dat;
		if(tre[ls].siz>=rk) return kth(ls,rk);
		return kth(rs,rk-tre[ls].siz-1);
	}
	int ask_pre(int val) 
	{
		int x=0,y=0;
		split(root,val-1,x,y);
		int pos=x;
		while(tre[pos].r) pos=tre[pos].r;
		root=merge(x,y);
		return tre[pos].dat; 
	}
	int ask_suf(int val)
	{
		int x=0,y=0;
		split(root,val,x,y);
		int pos=y;
		while(tre[pos].l) pos=tre[pos].l;
		root=merge(x,y);
		return tre[pos].dat;
	}
}T;
int n;
#undef int
int main()
{
	#define int long long
	srand(time(0));
	n=read();
	for(int i=1,opt,x;i<=n;i++)
	{
		opt=read(); x=read();
		if(opt==1) T.insert(x);
		else if(opt==2) T.del(x);
		else if(opt==3) printf("%lld\n",T.find(x));
		else if(opt==4) printf("%lld\n",T.kth(T.root,x));
		else if(opt==5) printf("%lld\n",T.ask_pre(x));
		else printf("%lld\n",T.ask_suf(x));
	}
	return 0;
}

P3391 文艺平衡树

FHQ-Treap

#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"Test: "<<endl
#define ls tre[x].l
#define rs tre[x].r
using namespace std;
inline int read()
{
	int x=0,f=1; char ch=getchar();
	while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
const int N=1e5+10;
struct FHQ_Treap
{
	int all,root;
	struct Node
	{
		int l,r,siz,dat,key,laz;
	}tre[N];
	int New(int val)
	{
		tre[++all]=(Node){0,0,1,val,rand(),0};
		return all;
	}
	void push_up(int x){tre[x].siz=tre[ls].siz+tre[rs].siz+1;}
	void split(int x,int pos,int &u,int &v)
	{
		if(!x) return u=v=0,void();
		push_down(x);
		if(pos<=tre[ls].siz) v=x,split(ls,pos,u,ls);
		else u=x,split(rs,pos-tre[ls].siz-1,rs,v);
		push_up(x);
	}
	int merge(int x,int y) 
	{
		if(!x||!y) return x+y;
		push_down(x); push_down(y);
		if(tre[x].key>tre[y].key)
			return tre[x].r=merge(tre[x].r,y),push_up(x),x;
		return tre[y].l=merge(x,tre[y].l),push_up(y),y;
	}
	void push_down(int x)
	{
		if(!x||!tre[x].laz) return ;
		tre[x].laz=0; swap(ls,rs);
		if(ls) tre[ls].laz^=1;
		if(rs) tre[rs].laz^=1;
	}
	void reverse(int l,int r)
	{
		int x=0,y=0,z=0;
		split(root,r,x,z);
		split(x,l-1,x,y);
		tre[y].laz^=1;
		root=merge(merge(x,y),z);
	}
	void print(int x)
	{
		if(!x) return ;
		push_down(x); print(ls);
		printf("%lld ",tre[x].dat);
		print(rs);
	}
}T;
int n,m;
#undef int
int main()
{
	#define int long long
	srand(time(0));
	n=read(); m=read();
	for(int i=1;i<=n;i++)
		T.root=T.merge(T.root,T.New(i));
	for(int i=1,l,r;i<=m;i++)
	{
		l=read(); r=read();
		T.reverse(l,r);
	}
	T.print(T.root);
	return 0;
}

回滚莫队

#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"Pass"<<endl
using namespace std;
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
const int N=1e5+10;
int n,m,r,len,maxn,top,pos[N],s[N],ans[N],li[N],ri[N];
struct Node
{
	int l,r,id;
	bool friend operator < (Node x,Node y)
	{
		if(pos[x.l]==pos[y.l])	return x.r<y.r;
		return x.l<y.l;
	}
}q[N];
struct node
{
	bool opt;	int id,val;
}sta[N<<1];
signed main()
{
	n=read();	m=read();
	len=sqrt(n);
	for(int i=1;i<=n;i++)
		s[i]=read(),pos[i]=i/len+1;
	for(int i=1;i<=m;i++)
		q[i].l=read(),q[i].r=read(),q[i].id=i;
	sort(q+1,q+m+1);
	for(int i=1;i<=m;i++)
	{
		if(pos[q[i].l]!=pos[q[i-1].l])
		{
			maxn=0;	r=pos[q[i].l]*len;
			for(int j=1;j<=n;j++)
				li[j]=ri[j]=0;
		}
		while(r<q[i].r)
		{
			r++;
			li[s[r]]=li[s[r]-1]+1;
			ri[s[r]]=ri[s[r]+1]+1;
			int temp=li[s[r]]+ri[s[r]]-1;
			maxn=max(maxn,temp);
			li[s[r]+ri[s[r]]-1]=temp;
			ri[s[r]-li[s[r]]+1]=temp;
		}
		int rec=maxn;
		for(int j=q[i].l;j<=min(q[i].r,pos[q[i].l]*len);j++)
		{
			li[s[j]]=li[s[j]-1]+1;
			ri[s[j]]=ri[s[j]+1]+1;
			sta[++top]=(node){0,s[j]-li[s[j]]+1,ri[s[j]-li[s[j]]+1]};
			sta[++top]=(node){1,ri[s[j]]+s[j]-1,li[ri[s[j]]+s[j]-1]};
			int temp=li[s[j]]+ri[s[j]]-1;
			rec=max(rec,temp);
			li[s[j]+ri[s[j]]-1]=temp;
			ri[s[j]-li[s[j]]+1]=temp;
		}
		while(top)
		{
			if(!sta[top].opt)	ri[sta[top].id]=sta[top].val;
			else	li[sta[top].id]=sta[top].val;
			top--;
		}
		for(int j=q[i].l;j<=min(q[i].r,pos[q[i].l]*len);j++)
			li[s[j]]=ri[s[j]]=0;
		ans[q[i].id]=rec;
	}
	for(int i=1;i<=m;i++)
		printf("%lld\n",ans[i]);
	return 0;
}

笛卡尔树

/*
给定一个 1~n的排列 p,构建其笛卡尔树。

即构建一棵二叉树,满足:

    每个节点的编号满足二叉搜索树的性质。
    节点 i 的权值为 pi,每个节点的权值满足小根堆的性质。

*/
void build()
{
	int top=0,pos=0;
	for(int i=1;i<=n;i++)
	{
		pos=top;
		while(pos&&p[sta[pos]]>p[i]) pos--;
		if(pos) rs[sta[pos]]=i;
		if(pos<top) ls[i]=sta[pos+1];
		sta[++pos]=i; top=pos;
	}
}

虚树

bool comp(int x,int y)
{
	return dfn[x]<dfn[y];
}
void build(int x)
{
	if(!top)
	{
		sta[++top]=x;
		return ;
	}
	int lca=LCA_ask(x,sta[top]);
	while(top>1&&dep[lca]<dep[sta[top-1]])
	{
		e2.add(sta[top-1],sta[top]);
		e2.add(sta[top],sta[top-1]);
		top--;
	}
	if(dep[lca]<dep[sta[top]])
	{
		e2.add(lca,sta[top]);
		e2.add(sta[top],lca);
		top--;
	}
	if(!top||sta[top]!=lca)
		sta[++top]=lca;
	sta[++top]=x;
}
int main()
{
	while(Q--)
	{
		for(int i=1;i<=m;i++)
		{
			scanf("%d",&q[i]);
			vis[q[i]]=true;
			ans[q[i]]=0;
		}
		if(!vis[1])
		{
			flag=true;
			q[++m]=1;
		}
		for(int i=1;i<=m;i++)
			s[i]=q[i];
		sort(s+1,s+m+1,comp);
		for(int i=1;i<=m;i++)
			build(s[i]);
		if(top)
			while(--top)
			{
				e2.add(sta[top],sta[top+1]);
				e2.add(sta[top+1],sta[top]);
			}
	}
}

P2479捉迷藏

KDTree

#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"Test: "<<endl
#define ls tre[x].l
#define rs tre[x].r
using namespace std;
inline int read()
{
	int x=0,f=1; char ch=getchar();
	while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
const int N=1e5+10,INF=1e18;
bool comp;
int maxn[N],minn[N];
struct Node
{
	int d[2],id;
	bool friend operator < (Node x,Node y)
		{return x.d[comp]>y.d[comp];}
}s[N],temp;
int dist(Node x,Node y)
{
	return abs(x.d[0]-y.d[0])+abs(x.d[1]-y.d[1]);
}
struct K_DTree
{
	int root,all;
	struct Tree
	{
		int l,r,mn[2],mx[2];
		Node dat;
	}tre[N];
	void push_up(int x)
	{
		for(int i=0;i<=1;i++)
		{
			tre[x].mn[i]=tre[x].mx[i]=tre[x].dat.d[i];
			if(ls) tre[x].mn[i]=min(tre[x].mn[i],tre[ls].mn[i]),
				tre[x].mx[i]=max(tre[x].mx[i],tre[ls].mx[i]);
			if(rs) tre[x].mn[i]=min(tre[x].mn[i],tre[rs].mn[i]),
				tre[x].mx[i]=max(tre[x].mx[i],tre[rs].mx[i]);
		}
	}
	void build(int &x,int l,int r,int opt)
	{
		int mid=(l+r)>>1; comp=opt;
		nth_element(s+l,s+mid,s+r+1);
		tre[x=++all].dat=s[mid];
		if(l<mid) build(ls,l,mid-1,opt^1);
		if(r>mid) build(rs,mid+1,r,opt^1);
		push_up(x);
	}
	int KD_max(int x,Node p)
	{
		if(!x) return -INF;
		int sum=0;
		for(int i=0;i<=1;i++)
			sum+=max(abs(tre[x].mn[i]-p.d[i]),abs(tre[x].mx[i]-p.d[i]));
		return sum;
	}
	int KD_min(int x,Node p)
	{
		if(!x) return INF;
		int sum=0;
		for(int i=0;i<=1;i++)
			sum+=max(0ll,tre[x].mn[i]-p.d[i])+max(0ll,p.d[i]-tre[x].mx[i]);
		return sum;
	}
	void query_max(int x,Node p)
	{
		if(!x) return ;
		int rec=dist(tre[x].dat,p);
		if(rec>maxn[p.id]) maxn[p.id]=rec,temp=tre[x].dat;
		int mxl=KD_max(ls,p),mxr=KD_max(rs,p);
		if(mxl>mxr)
		{
			if(mxl>maxn[p.id]) query_max(ls,p);
			if(mxr>maxn[p.id]) query_max(rs,p);
		}
		else
		{
			if(mxr>maxn[p.id]) query_max(rs,p);
			if(mxl>maxn[p.id]) query_max(ls,p);
		}
	}
	void query_min(int x,Node p)
	{
		if(!x) return ;
		int rec=dist(tre[x].dat,p);
		if(rec<minn[p.id]&&tre[x].dat.id!=p.id)
			minn[p.id]=rec,temp=tre[x].dat;
		int mnl=KD_min(ls,p),mnr=KD_min(rs,p);
		if(mnl<mnr)
		{
			if(mnl<minn[p.id]) query_min(ls,p);
			if(mnr<minn[p.id]) query_min(rs,p);
		}
		else
		{
			if(mnr<minn[p.id]) query_min(rs,p);
			if(mnl<minn[p.id]) query_min(ls,p);
		}
	} 
}T;
int n,ans=INF;
#undef int
int main()
{
	#define int long long
	//实际上就是每一层选择不同维度的排序方式,记录每一个区间内可能存在的最优解 
	n=read();
	for(int i=1;i<=n;i++)
		s[i].d[0]=read(),s[i].d[1]=read(),s[i].id=i;
	T.build(T.root,1,n,0);
	memset(minn,0x7f,sizeof(minn));
	for(int i=1;i<=n;i++)
	{
		T.query_max(T.root,s[i]);
		maxn[temp.id]=maxn[s[i].id];
		T.query_min(T.root,s[i]);
		minn[temp.id]=minn[s[i].id];
		ans=min(ans,maxn[s[i].id]-minn[s[i].id]);
	}
	printf("%lld",ans);
	return 0;
}
posted @ 2023-09-12 21:22  Varuxn  阅读(38)  评论(2编辑  收藏  举报