LCT题集(spojqtree全套+动态点分)

qtree1(树剖+线段树 1年前代码略丑)

#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
#include<cstring>
#include<cstdio>
#include<stack>
#include<queue>
#define N 10005
#define INF 0x3f3f3f3f
using namespace std;
int pos;
int son[N];
int n,m;
int s[N];
bool vis[N];
typedef struct node {
	int v;
	int u;
	int date;
} node;
vector<node>vec[N];
node b[N];
void inte() {
	pos=0;
	for(int i=1; i<=n; i++)  son[i]=-1;
}
int fa[N];
int num[N];
int deep[N];
void dfs(int v,int pre,int w) {
	fa[v]=pre;
	num[v]=1;
	deep[v]=w;
	for(int i=0; i<vec[v].size(); i++) {
		int u=vec[v][i].u;
		if(u!=pre) {
			s[u]=vec[v][i].date;
			dfs(u,v,w+1);
			num[v]+=num[u];
			if(son[v]==-1||num[son[v]]<num[u]) {
				son[v]=u;
			}
		}
	}
}
int p[N];
int tp[N];
int fp[N];
void biao(int v,int sd) {
	p[v]=++pos;
	fp[p[v]]=v;
	tp[v]=sd;
	if(son[v]==-1)  return ;
	biao(son[v],sd);
	for(int i=0; i<vec[v].size(); i++) {
		int u=vec[v][i].u;
		if(u!=fa[v]&&u!=son[v]) {
			biao(u,u);
		}
	}
}
typedef struct list {
	int first;
	int end;
	int mmax;
	int flag;
	int mmin;
} list;
list a[4*N];
void built(int root,int first,int end) {
	if(first==end) {
		a[root].first=first;
		a[root].end=end;
		a[root].mmax=s[fp[first]];
		a[root].mmin=s[fp[first]];
		a[root].flag=0;
		return ;
	}
	int mid=(first+end)/2;
	built(root*2,first,mid);
	built(root*2+1,mid+1,end);
	a[root].first=a[root*2].first;
	a[root].end=a[root*2+1].end;
	a[root].mmax=max(a[root*2].mmax,a[root*2+1].mmax);
	a[root].mmin=min(a[root*2].mmin,a[root*2+1].mmin);
	a[root].flag=0;
}
void update(int root,int first,int end,int e,int w) {
	if(first==end) {
		a[root].mmax=w;
		a[root].mmin=w;
		a[root].flag=0;
		return ;
	}
	if(a[root].flag!=0) {
		if(a[root].flag==1) {
			int t=a[root*2].mmax;
			a[root*2].mmax=(-1)*a[root*2].mmin;
			a[root*2].mmin=(-1)*t;
			t=a[root*2+1].mmax;
			a[root*2+1].mmax=(-1)*a[root*2+1].mmin;
			a[root*2+1].mmin=(-1)*t;
		}
		a[root*2].flag=(a[root].flag+a[root*2].flag)%2;
		a[root*2+1].flag=(a[root].flag+a[root*2+1].flag)%2;
		a[root].flag=0;
	}
	int mid=(first+end)/2;
	if(e<=mid)  update(root*2,first,mid,e,w);
	else update(root*2+1,mid+1,end,e,w);
	a[root].mmin=min(a[root*2].mmin,a[root*2+1].mmin);
	a[root].mmax=max(a[root*2].mmax,a[root*2+1].mmax);
}
void U(int root,int first,int end,int l,int r) {
	if(p[l]<=first&&end<=p[r]) {
    	int t=a[root].mmax;
		a[root].mmax=(-1)*a[root].mmin;
		a[root].mmin=(-1)*t;
        a[root].flag=(a[root].flag+1)%2; 
		return ;
	}
	if(a[root].flag!=0) {
		if(a[root].flag==1) {
			int t=a[root*2].mmax;
			a[root*2].mmax=(-1)*a[root*2].mmin;
			a[root*2].mmin=(-1)*t;
			t=a[root*2+1].mmax;
			a[root*2+1].mmax=(-1)*a[root*2+1].mmin;
			a[root*2+1].mmin=(-1)*t;
		}
		a[root*2].flag=(a[root].flag+a[root*2].flag)%2;
		a[root*2+1].flag=(a[root].flag+a[root*2+1].flag)%2;
		a[root].flag=0;
	}
	int mid=(first+end)/2;
	if(p[l]<=mid) U(root*2,first,mid,l,r);
	if(p[r]>mid) U(root*2+1,mid+1,end,l,r);
	a[root].mmin=min(a[root*2].mmin,a[root*2+1].mmin);
	a[root].mmax=max(a[root*2].mmax,a[root*2+1].mmax);
}
int sum;
void Q(int root,int first,int end,int l,int r) {
	if(p[l]<=first&&end<=p[r]) {
		sum=max(sum,a[root].mmax);
		return ;
	}
		if(a[root].flag!=0) {
		if(a[root].flag==1) {
			int t=a[root*2].mmax;
			a[root*2].mmax=(-1)*a[root*2].mmin;
			a[root*2].mmin=(-1)*t;
			t=a[root*2+1].mmax;
			a[root*2+1].mmax=(-1)*a[root*2+1].mmin;
			a[root*2+1].mmin=(-1)*t;
		}
		a[root*2].flag=(a[root].flag+a[root*2].flag)%2;
		a[root*2+1].flag=(a[root].flag+a[root*2+1].flag)%2;
		a[root].flag=0;
	}
	int mid=(first+end)/2;
	if(p[l]<=mid) Q(root*2,first,mid,l,r);
	if(p[r]>mid) Q(root*2+1,mid+1,end,l,r);
}
void Up(int u,int v) {
	int uu=tp[u];
	int vv=tp[v];
	while(uu!=vv) {
		if(deep[uu]<deep[vv]) {
			swap(u,v);
			swap(uu,vv);
		}
		U(1,1,n,uu,u);
		u=fa[uu];
		uu=tp[u];
	}
	if(deep[u]>deep[v])  swap(u,v);
	U(1,1,n,fp[p[u]+1],v);
}
int Max(int u,int v) {
	int uu=tp[u];
	int vv=tp[v];
	sum=-INF;
	while(uu!=vv) {
		if(deep[uu]<deep[vv]) {
			swap(u,v);
			swap(uu,vv);
		}
		Q(1,1,n,uu,u);
		u=fa[uu];
		uu=tp[u];
	}
	if(deep[u]>deep[v])  swap(u,v);
	Q(1,1,n,fp[p[u]+1],v);
	return sum;
}
int main() {
	int T;
	char aa[]="CHANGE";
	char bb[]="NEGATE";
	char cc[]="QUERY";
	char dd[]="DONE";
	char ch[50];
	scanf("%d",&T);
	while(T--) {
		scanf("%d",&n);
		memset(vis,0,sizeof(vis));
		for(int i=1; i<n; i++) {
			scanf("%d%d%d",&b[i].v,&b[i].u,&b[i].date);
			if(vis[b[i].u]==1) vis[b[i].v]=1;
			else vis[b[i].u]=1;
			node t;
			vec[b[i].v].push_back(b[i]);
			t.v=b[i].u;
			t.u=b[i].v;
			t.date=b[i].date;
			vec[b[i].u].push_back(t);
		}
		int tt;
		for(int i=1; i<=n; i++) {
			if(vis[i]==0) {
				tt=i;
				break;
			}
		}
		s[tt]=0;
		inte();
		dfs(tt,-1,1);
		biao(tt,tt);
		int u,v,r;
		int t1;
		getchar();
		built(1,1,n);
		while(scanf("%s",ch)==1&&strcmp(ch,dd)!=0) {
			if(strcmp(ch,aa)==0) {
				scanf("%d%d",&t1,&r);
				int g;
				if(deep[b[t1].v]<deep[b[t1].u]) g=b[t1].u;
				else g=b[t1].v;
				update(1,1,n,p[g],r);
			} else if(strcmp(ch,bb)==0) {
				scanf("%d%d",&u,&v);
				Up(u,v);
			} else if(strcmp(ch,cc)==0) {
				scanf("%d%d",&u,&v);
				int t2=Max(u,v);
				printf("%d\n",t2);
			}
		}
		for(int i=1; i<=n; i++)  vec[i].clear();
	}
	return 0;
}

 qtree2(lct 查询忘记传标记 WA死)

#include <bits/stdc++.h>
#define ll long long
const int MAXN=2e4+10;
using namespace std;
int ch[MAXN][2],res[MAXN],size[MAXN],pre[MAXN],key[MAXN];
bool rt[MAXN];
int n,cnt;ll sum[MAXN];
vector<pair<int,int> >vec[MAXN];
void newnode(int x,int vul){
	ch[x][0]=ch[x][1]=0;res[x]=pre[x]=0;sum[x]=key[x]=vul;
	rt[x]=1;size[x]=1;
}
void reverse(int r){
	if(!r)return ;
	swap(ch[r][0],ch[r][1]);
	res[r]^=1;
}
void push(int x){
	if(res[x]){
		reverse(ch[x][0]);
		reverse(ch[x][1]);
		res[x]^=1;
	}
}
void up(int x){
	sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+key[x];
	size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
}
void P(int x){
	if(!rt[x])P(pre[x]);
	push(x);
}
void Treavel(int x)
{
    if(x)
    {
        Treavel(ch[x][0]);
        printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size=%2d,key=%2d\n",x,ch[x][0],ch[x][1],pre[x],size[x],key[x]);
        Treavel(ch[x][1]);
    }
}
void debug(int rp)
{
	P(rp);
    printf("root:%d\n",rp);
    Treavel(rp);
}
void rotate(int x,int kind){
	int y=pre[x];
	pre[ch[x][kind]]=y;ch[y][!kind]=ch[x][kind];
	if(rt[y])rt[x]=1,rt[y]=0;
	else ch[pre[y]][ch[pre[y]][1]==y]=x;
	pre[x]=pre[y];ch[x][kind]=y;pre[y]=x;
	up(y);
}
void splay(int x){
	P(x);
	while(!rt[x]){
		if(rt[pre[x]])rotate(x,ch[pre[x]][0]==x);
		else{
			int y=pre[x];int kind=ch[pre[y]][0]==y;
			if(ch[y][kind]==x)rotate(x,!kind),rotate(x,kind);
			else rotate(y,kind),rotate(x,kind);
		}
	}
	up(x);
}
void access(int x){
	int y=0;
	while(x){
		splay(x);
		if(ch[x][1])rt[ch[x][1]]=1,pre[ch[x][1]]=x,ch[x][1]=0;
		ch[x][1]=y;up(x);
		if(y)rt[y]=0;
		y=x;x=pre[x];
	}
}
int find1(int x,int sz){
	push(x);
	if(sz==size[ch[x][0]]+1)return x;
	else if(sz<=size[ch[x][0]])return find1(ch[x][0],sz);
	else return find1(ch[x][1],sz-size[ch[x][0]]-1);
}
void mroot(int x){
	access(x);splay(x);reverse(x);
}
void Link(int u,int v){
	mroot(u);pre[u]=v;
}
ll querty(int u,int v){
	mroot(u);access(v);splay(v);
	return sum[v];
}
int Kth(int u,int v,int k){
	mroot(u);access(v);splay(u);
	return find1(u,2*k-1);
}
char str[11];
void dfs(int v,int pre){
	for(int i=0;i<vec[v].size();i++){
		if(vec[v][i].first!=pre){
			cnt++;newnode(cnt,vec[v][i].second);
			Link(vec[v][i].first,cnt);Link(cnt,v);
			dfs(vec[v][i].first,v);
		}
	}
}
int main(){
	int _;scanf("%d",&_);
	while(_--){
		scanf("%d",&n);cnt=n;int u,v,vul;
		for(int i=1;i<=n;i++)newnode(i,0);
		for(int i=1;i<n;i++){
			scanf("%d%d%d",&u,&v,&vul);
			vec[u].push_back(make_pair(v,vul));
			vec[v].push_back(make_pair(u,vul));
		}
		dfs(1,0);
		while(scanf("%s",str)!=EOF){
			if(str[1]=='O')break;
			else if(str[0]=='D')scanf("%d%d",&u,&v),printf("%lld\n",querty(u,v));
			else scanf("%d%d%d",&u,&v,&vul),printf("%d\n",Kth(u,v,vul));
		}
		for(int i=1;i<=cnt;i++)newnode(i,0);
		for(int i=1;i<=n;i++)vec[i].clear();
	}
	return 0;
}

 qtree3(树剖+线段树 求反竟然对拍跑了这么久)

#include <bits/stdc++.h>
const int inf=1e9;
const int MAXN=1e6+10;
using namespace std;
int minn[MAXN<<2];int n,m;
vector<int>vec[MAXN];
int p[MAXN],fp[MAXN],cnt,tp[MAXN];
int num[MAXN],dep[MAXN],fa[MAXN],son[MAXN];
void built(int rt,int l,int r){
	minn[rt]=inf;
	if(l==r)return ;
	int mid=(l+r)>>1;
	built(rt<<1,l,mid);
	built(rt<<1|1,mid+1,r);
}
void update(int rt,int l,int r,int t){
	if(l==r){
		if(minn[rt]==inf)minn[rt]=l;
		else minn[rt]=inf;
		return ;
	}
	int mid=(l+r)>>1;
	if(t<=mid)update(rt<<1,l,mid,t);
	else update(rt<<1|1,mid+1,r,t);
	minn[rt]=min(minn[rt<<1],minn[rt<<1|1]);
}
int ans;
void querty(int rt,int l,int r,int ql,int qr){
	if(ql<=l&&r<=qr){ans=min(ans,minn[rt]);return ;}
	int mid=(l+r)>>1;
	if(ql<=mid)querty(rt<<1,l,mid,ql,qr);
	if(qr>mid)querty(rt<<1|1,mid+1,r,ql,qr);
}
void dfs(int v,int pre,int deep){
	num[v]=1;dep[v]=deep+1;fa[v]=pre;
	for(int i=0;i<vec[v].size();i++){
		if(vec[v][i]!=pre){
			dfs(vec[v][i],v,deep+1);
			num[v]+=num[vec[v][i]];
			if(son[v]==-1||num[son[v]]<num[vec[v][i]])son[v]=vec[v][i];
		}
	}
}
void dfs1(int v,int td){
	p[v]=++cnt;fp[p[v]]=v;tp[v]=td;
	if(son[v]!=-1)dfs1(son[v],td);
	for(int i=0;i<vec[v].size();i++)if(vec[v][i]!=son[v]&&vec[v][i]!=fa[v])dfs1(vec[v][i],vec[v][i]);
}
int slove(int v){
	int vv=tp[v];ans=inf;
	while(vv!=1){
		querty(1,1,n,p[vv],p[v]);
		v=fa[vv];vv=tp[v];
	}
	querty(1,1,n,p[1],p[v]);
	return ans;
}
int main(){
	scanf("%d%d",&n,&m);int u,v;cnt=0;
	built(1,1,n);
	for(int i=1;i<=n;i++)son[i]=-1;
	for(int i=1;i<n;i++)scanf("%d%d",&u,&v),vec[u].push_back(v),vec[v].push_back(u);
	dfs(1,0,0);dfs1(1,1);
	int op;
	for(int i=1;i<=m;i++){
		scanf("%d%d",&op,&v);
		if(op==0)update(1,1,n,p[v]);
		else{
			int t=slove(v);
			printf("%d\n",t==inf?-1:fp[t]);
		}
	}
	return 0;
}

 qtree4

1.颜色翻转

2.求树中最长白色点对距离

题解: 这本是动态点分模板题 然而不会啊  所以我们LCT来搞一搞  维护子树信息

首先 维护maxx 表示以这个节点为根的最长距离

   维护lmax 表示在这个节点为根是的白色节点到这条重链最左边的最长距离

   维护rmax 表示在这个节点为根是的白色节点到这条重链最右边的最长距离

   两个multiset 分别维护子树中的答案 以及子树中白色节点到这个节点的距离

   然后每次合并答案取max即可 细节较多 建议分类画图考虑

#include <bits/stdc++.h>
#define ll long long
#define getchar getchar_unlocked 
const int MAXN=2e5+10;
const int inf=0x3f3f3f3f;
using namespace std;
inline void read(int &x){
    x=0;char c=getchar();int f(0);
    while(c<'0'||c>'9')f|=(c=='-'),c=getchar();
    while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
    if(f)x=-x;
}
int ch[MAXN][2],pre[MAXN];
int lmax[MAXN],rmax[MAXN],maxx[MAXN],sum[MAXN],key[MAXN],vul[MAXN],len[MAXN];
bool rt[MAXN];
multiset<int>smax[MAXN],s[MAXN];
multiset<int>::iterator ite;
vector<pair<int,int> >vec[MAXN];
inline int get_max(int x){
	if(smax[x].begin()==smax[x].end())return -1*inf;
	ite=smax[x].end();ite--;
	return (*ite);
}
inline int get_max1(int x){
	if(s[x].begin()==s[x].end())return -1*inf;
	ite=s[x].end();ite--;
	return (*ite);
}
inline int get_max2(int x){
	if(s[x].size()<2)return -1*inf;
	ite=s[x].end();ite--;ite--;
	return (*ite);
}
void newnode(int x){
	ch[x][0]=ch[x][1]=pre[x]=0;sum[x]=len[x]=0;
	key[x]=-inf;rt[x]=1;lmax[x]=-inf;maxx[x]=-1*inf;rmax[x]=-inf;
}
int t1,t2,t3;
void up(int x){
	t1=get_max(x);t2=get_max1(x);t3=get_max2(x);
	sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+len[x];
	maxx[x]=max(maxx[ch[x][0]],maxx[ch[x][1]]);maxx[x]=max(maxx[x],t1);
	maxx[x]=max(maxx[x],len[x]+rmax[ch[x][0]]+max(key[x],(max(t2,lmax[ch[x][1]]))));
	maxx[x]=max(maxx[x],lmax[ch[x][1]]+max(key[x],(max(t2,len[x]+rmax[ch[x][0]]))));
	maxx[x]=max(maxx[x],t2+t3);maxx[x]=max(maxx[x],t2+key[x]);
	if(key[x]==0)maxx[x]=max(maxx[x],0);
	lmax[x]=max(lmax[ch[x][0]],max(len[x]+max(t2,key[x]),lmax[ch[x][1]]+len[x])+sum[ch[x][0]]);
	rmax[x]=max(rmax[ch[x][1]],max(max(t2,key[x]),rmax[ch[x][0]]+len[x])+sum[ch[x][1]]);
}
void rotate(int x,int kind){
	int y=pre[x];
	ch[y][!kind]=ch[x][kind];pre[ch[x][kind]]=y;
	if(rt[y])rt[x]=1,rt[y]=0;
	else ch[pre[y]][ch[pre[y]][1]==y]=x;
	pre[x]=pre[y];ch[x][kind]=y;pre[y]=x;
	up(y);
}
void splay(int x){
	while(!rt[x]){
		if(rt[pre[x]])rotate(x,ch[pre[x]][0]==x);
		else{
			int y=pre[x];int kind=ch[pre[y]][0]==y;
			if(ch[y][kind]==x)rotate(x,!kind),rotate(x,kind);
			else rotate(y,kind),rotate(x,kind);
		}
	}
	up(x);
}
void access(int x){
	int y=0;
	while(x){
		splay(x);
		if(ch[x][1])pre[ch[x][1]]=x,rt[ch[x][1]]=1,smax[x].insert(maxx[ch[x][1]]),s[x].insert(lmax[ch[x][1]]);
		if(y)rt[y]=0,smax[x].erase(smax[x].lower_bound(maxx[y])),s[x].erase(s[x].lower_bound(lmax[y]));
		ch[x][1]=y;up(x);
		y=x;x=pre[x];
	}
}
void change(int x){
	access(x);splay(x);
	if(key[x]==-1*inf)key[x]=0;
	else key[x]=-1*inf;
	up(x);
}
int querty(int x){
	access(x);splay(x);
	return maxx[x];
}
void dfs(int v,int fa){
	key[v]=0;
	for(int i=0;i<vec[v].size();i++){
		if(vec[v][i].first!=fa){
			pre[vec[v][i].first]=v;len[vec[v][i].first]=vec[v][i].second;
			dfs(vec[v][i].first,v);
			smax[v].insert(maxx[vec[v][i].first]);
			s[v].insert(lmax[vec[v][i].first]);
		}
	}
 	up(v);
 	//cout<<v<<" "<<maxx[v]<<" "<<lmax[v]<<" "<<rmax[v]<<endl;
}
char str[11];
int main(){
	int n;read(n);int u,v,vul;
	for(int i=0;i<=n;i++)newnode(i);
	for(int i=1;i<n;i++)read(u),read(v),read(vul),vec[u].push_back(make_pair(v,vul)),vec[v].push_back(make_pair(u,vul));
	dfs(1,0);int m;read(m);
	while(m--){
		scanf("%s",str);
		if(str[0]=='A'){
			int t=querty(1);
			if(t<0)puts("They have disappeared.");
			else printf("%d\n",t);
		}
		else{read(u);change(u);}
	}
	return 0;
}

 qtree5(4的简化版本 只需要维护子树到根路径的multiset 已经lmin rmin即可)

#include <bits/stdc++.h>
const int MAXN=1e5+10;
const int inf=1e9;
using namespace std;
int minn[MAXN],ch[MAXN][2],pre[MAXN],lmin[MAXN],rmin[MAXN],size[MAXN],key[MAXN];
bool rt[MAXN];
multiset<int>s[MAXN];
vector<int>vec[MAXN];
void Treavel(int x)
{
    if(x)
    {
    //  cout<<x<<endl;
        Treavel(ch[x][0]);
        printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size=%2d,key=%2d,min=%2d,lmin=%2d,rmin=%2d\n",x,ch[x][0],ch[x][1],pre[x],size[x],key[x],minn[x],lmin[x],rmin[x]);
        Treavel(ch[x][1]);
    }
}
void debug(int rp)
{
    printf("root:%d\n",rp);
    Treavel(rp);
}
void newnode(int x){
	minn[x]=key[x]=lmin[x]=rmin[x]=inf;ch[x][0]=ch[x][1]=0;
	pre[x]=0;size[x]=1;rt[x]=1;
}
int get_min(int x){
	if(s[x].begin()==s[x].end())return inf;
	return (*s[x].begin());
}
void up(int x){
	size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
	int x1=min(get_min(x),rmin[ch[x][0]]);
	int x2=min(get_min(x),lmin[ch[x][1]]);
	minn[x]=min(key[x],min(x1,x2)+1);
	rmin[x]=min(rmin[ch[x][1]],size[ch[x][1]]+x1+1);
	lmin[x]=min(lmin[ch[x][0]],size[ch[x][0]]+x2+1);
	rmin[x]=min(rmin[x],key[x]+size[ch[x][1]]);
	lmin[x]=min(lmin[x],key[x]+size[ch[x][0]]);
}
void rotate(int x,int kind){
	int y=pre[x];
	pre[ch[x][kind]]=y;ch[y][!kind]=ch[x][kind];
	if(rt[y])rt[y]=0,rt[x]=1;
	else ch[pre[y]][ch[pre[y]][1]==y]=x;
	pre[x]=pre[y];ch[x][kind]=y;pre[y]=x;
	up(y);
}
void splay(int x){
	while(!rt[x]){
		if(rt[pre[x]])rotate(x,ch[pre[x]][0]==x);
		else{
			int y=pre[x];int kind=ch[pre[y]][0]==y;
			if(ch[y][kind]==x)rotate(x,!kind),rotate(x,kind);
			else rotate(y,kind),rotate(x,kind);
		}
	}
	up(x);
}
void access(int x){
	int y=0;
	while(x){
		splay(x);
		if(ch[x][1])pre[ch[x][1]]=x,rt[ch[x][1]]=1,s[x].insert(lmin[ch[x][1]]);
		if(y)rt[y]=0,s[x].erase(s[x].lower_bound(lmin[y]));
		ch[x][1]=y;up(x);
		y=x;x=pre[x];
	}
}
void Link(int u,int v){
	access(u);splay(u);
	access(v);splay(v);
	pre[u]=v;s[v].insert(lmin[u]);up(v);
}
void change(int x){
	access(x);splay(x);
	if(key[x]==inf)key[x]=0;
	else key[x]=inf;
	up(x);
}
int querty(int u){
	access(u);splay(u);
	if(minn[u]>=inf)return -1;
	return minn[u];
}
void dfs(int v,int pre){
	for(int i=0;i<vec[v].size();i++){
		if(vec[v][i]!=pre){
			Link(vec[v][i],v);
			dfs(vec[v][i],v);
		}
	}
}
int main(){
	key[0]=minn[0]=inf;lmin[0]=rmin[0]=inf;
	int n;scanf("%d",&n);int u,v;
	for(int i=1;i<=n;i++)newnode(i);
	for(int i=1;i<n;i++)scanf("%d%d",&u,&v),vec[u].push_back(v),vec[v].push_back(u);
	dfs(1,0);
	int m;scanf("%d",&m);int op;
	for(int i=1;i<=m;i++){
		scanf("%d%d",&op,&u);
		if(op==0)change(u);
		else printf("%d\n",querty(u));
	}
}

 qtree6

1.颜色翻转

2.求这个点所在颜色的联通快

首先:我们考虑到 这点颜色翻转 去掉与父亲的边 在翻转后的颜色里面和父亲连边 这样能够保证在当前父亲子树中除了父亲节点以为其他节点和当前节点颜色一致 那么这个题就转化模型为 删边加边维护联通快的大小 lct即可 注意树不能换根 因为父子关系不能改变

#include <bits/stdc++.h>
const int MAXN=1e5+10;
using namespace std;
int ch[2][MAXN][2],pre[2][MAXN],size[2][MAXN],size1[2][MAXN];
int key[MAXN],fa[MAXN];
bool rt[2][MAXN];
vector<int>vec[MAXN];
struct FastIO
{
    static const int S=200;
    int wpos;
    char wbuf[S];
    FastIO():wpos(0){}
    inline int xchar()
    {
        static char buf[S];
        static int len=0,pos=0;
        if(pos==len) pos=0,len=fread(buf,1,S,stdin);
        if(pos==len) exit(0);
        return buf[pos++];
    }
    inline int read()
    {
        int s=1,c=xchar(),x=0;
        while(c<=32) c=xchar();
        if(c=='-') s=-1,c=xchar();
        for(;'0'<=c&&c<='9';c=xchar()) x=x*10+c-'0';
        return x*s;
    }
    ~FastIO()
    {
        if(wpos) fwrite(wbuf,1,wpos,stdout),wpos=0;
    }
}io;
inline void newnode(int id,int x){
    ch[id][x][0]=ch[id][x][1]=0;pre[id][x]=0;
    size1[id][x]=1;size[id][x]=0;
    rt[id][x]=1;
}
inline void up(int id,int x){size1[id][x]=size1[id][ch[id][x][0]]+size1[id][ch[id][x][1]]+size[id][x]+1;}
inline void rotate(int id,int x,int kind){
    int y=pre[id][x];
    pre[id][ch[id][x][kind]]=y;ch[id][y][!kind]=ch[id][x][kind];
    if(rt[id][y])rt[id][x]=1,rt[id][y]=0;
    else ch[id][pre[id][y]][ch[id][pre[id][y]][1]==y]=x;
    pre[id][x]=pre[id][y];ch[id][x][kind]=y;pre[id][y]=x;
    up(id,y);
}
inline void splay(int id,int x){
    while(!rt[id][x]){
        if(rt[id][pre[id][x]])rotate(id,x,ch[id][pre[id][x]][0]==x);
        else{
            int y=pre[id][x];int kind=ch[id][pre[id][y]][0]==y;
            if(ch[id][y][kind]==x)rotate(id,x,!kind),rotate(id,x,kind);
            else rotate(id,y,kind),rotate(id,x,kind);
        }
    }
    up(id,x);
}
inline void access(int id,int x){
    int y=0;
    while(x){
        //cout<<x<<" "<<y<<":::"<<" "<<pre[id][4]<<endl;
        splay(id,x);
        if(ch[id][x][1])pre[id][ch[id][x][1]]=x,rt[id][ch[id][x][1]]=1,size[id][x]+=size1[id][ch[id][x][1]];
        if(y)rt[id][y]=0,size[id][x]-=size1[id][y];
        ch[id][x][1]=y;up(id,x);
        y=x;x=pre[id][x];
        //cout<<x<<" "<<y<<endl;
    }
}
inline void Link(int id,int u,int v){
    //cout<<id<<"===="<<u<<" "<<v<<endl;
    access(id,u);splay(id,u);
    //cout<<"sb"<<endl;
    access(id,v);splay(id,v);
    //cout<<"sb"<<endl;
    pre[id][u]=v;size[id][v]+=size1[id][u];up(id,v);
}
inline void destory(int id,int u,int v){
    access(id,u);splay(id,v);
    pre[id][u]=0;ch[id][v][1]=0;rt[id][u]=1;
    up(id,v);
}
inline int froot(int id,int x){
    access(id,x);
    splay(id,x);
    while(ch[id][x][0])x=ch[id][x][0];
    return x;
}
inline int querty(int id,int x){
    x=froot(id,x);
    splay(id,x);
    if(key[x]==id)return size1[id][x];
    return size1[id][ch[id][x][1]];
}
inline void dfs(int v,int pre){
    fa[v]=pre;
    for(int i=0;i<vec[v].size();i++){
        if(vec[v][i]!=pre){
            Link(0,vec[v][i],v);
            dfs(vec[v][i],v);
        }
    }
}
int main(){
    int n;n=io.read();
    for(int i=1;i<=n;i++)newnode(0,i),newnode(1,i),key[i]=0;
    int u,v;
    for(int i=1;i<n;i++){
        u=io.read();v=io.read();
        vec[u].push_back(v);vec[v].push_back(u);
    }
    dfs(1,0);
    int m,op;m=io.read();
    for(int i=1;i<=m;i++){
        op=io.read();v=io.read();
        if(op==1){
            if(fa[v]){destory(key[v],v,fa[v]);Link(key[v]^1,v,fa[v]);}
            key[v]^=1;
        }
        else printf("%d\n",querty(key[v],v));
    }
    return 0;
}

 qtree7

1.翻转颜色

2.修改点权

3.查询联通颜色的最大点权

题解:qtree6的做法 多一个multiset维护子树最大值即可

#include <bits/stdc++.h>
const int MAXN=2e5+10;
const int inf=2e9;
using namespace std;
int pre[2][MAXN],ch[2][MAXN][2],vul[2][MAXN],maxx[2][MAXN];
bool rt[2][MAXN];int key[MAXN],fa[MAXN];
multiset<int>s[2][MAXN];
multiset<int>::iterator ite;
vector<int>vec[MAXN];
inline void newnode(int id,int x){
    pre[id][x]=0;ch[id][x][0]=ch[id][x][1]=0;rt[id][x]=1;
}
inline int get_max(int id,int x){
    if(s[id][x].size()==0)return -1*inf;
    ite=s[id][x].end();ite--;
    return (*ite);
}
inline void up(int id,int x){
    maxx[id][x]=vul[id][x];maxx[id][x]=max(maxx[id][x],get_max(id,x));
    maxx[id][x]=max(maxx[id][x],max(maxx[id][ch[id][x][0]],maxx[id][ch[id][x][1]]));
}
inline void rotate(int id,int x,int kind){
    int y=pre[id][x];
    pre[id][ch[id][x][kind]]=y;ch[id][y][!kind]=ch[id][x][kind];
    if(rt[id][y])rt[id][y]=0,rt[id][x]=1;
    else ch[id][pre[id][y]][ch[id][pre[id][y]][1]==y]=x;
    pre[id][x]=pre[id][y];ch[id][x][kind]=y;pre[id][y]=x;
    up(id,y);
}
inline void splay(int id,int x){
    while(!rt[id][x]){
        if(rt[id][pre[id][x]])rotate(id,x,ch[id][pre[id][x]][0]==x);
        else{
            int y=pre[id][x];int kind=ch[id][pre[id][y]][0]==y;
            if(ch[id][y][kind]==x)rotate(id,x,!kind),rotate(id,x,kind);
            else rotate(id,y,kind),rotate(id,x,kind);
        }
    }
    up(id,x);
}
inline void access(int id,int x){
    int y=0;
    while(x){
        splay(id,x);
        if(ch[id][x][1])rt[id][ch[id][x][1]]=1,pre[id][ch[id][x][1]]=x,s[id][x].insert(maxx[id][ch[id][x][1]]);
        if(y)rt[id][y]=0,s[id][x].erase(s[id][x].lower_bound(maxx[id][y]));
        ch[id][x][1]=y;up(id,x);
        y=x;x=pre[id][x];
    }
}
inline void Link(int id,int u,int v){
    access(id,u);splay(id,u);
    access(id,v);splay(id,v);
    pre[id][u]=v;s[id][v].insert(maxx[id][u]);up(id,v);
}
inline void destory(int id,int u,int v){
    access(id,u);splay(id,v);
    pre[id][u]=0;rt[id][u]=1;ch[id][v][1]=0;up(id,v);
}
inline int froot(int id,int x){
    access(id,x);
    splay(id,x);
    while(ch[id][x][0])x=ch[id][x][0];
    return x;
}
inline int querty(int id,int x){
    x=froot(id,x);
    splay(id,x);
    if(key[x]==id)return maxx[id][x];
    return maxx[id][ch[id][x][1]];
} 
inline void change(int x,int t){
    access(0,x);splay(0,x);vul[0][x]=t;up(0,x);
    access(1,x);splay(1,x);vul[1][x]=t;up(1,x);
}
void dfs(int x,int pre){
    fa[x]=pre;
    for(int i=0;i<vec[x].size();i++){
        if(vec[x][i]!=pre){
            Link(key[vec[x][i]],vec[x][i],x);
            dfs(vec[x][i],x);
        }
    }
}
int main(){
    maxx[0][0]=maxx[1][0]=vul[0][0]=vul[1][0]=-1*inf;
    int n;scanf("%d",&n);int u,v;
    for(int i=1;i<=n;i++)newnode(0,i),newnode(1,i);
    for(int i=1;i<n;i++)scanf("%d%d",&u,&v),vec[u].push_back(v),vec[v].push_back(u);
    for(int i=1;i<=n;i++)scanf("%d",&key[i]);
    for(int i=1;i<=n;i++)scanf("%d",&maxx[0][i]),maxx[1][i]=vul[0][i]=vul[1][i]=maxx[0][i];
    dfs(1,0);
    int m;scanf("%d",&m);int op;
    for(int i=1;i<=m;i++){
        scanf("%d%d",&op,&u);
        if(op==0)printf("%d\n",querty(key[u],u));
        else if(op==1){
            if(fa[u])destory(key[u],u,fa[u]),Link(key[u]^1,u,fa[u]);
            key[u]^=1;
        }
        else scanf("%d",&v),change(u,v);
    }
    return 0;
}

 bzoj1095(qtree4的简化版 边权设置为1即可)

/**************************************************************
    Problem: 1095
    User: c20161007
    Language: C++
    Result: Accepted
    Time:9136 ms
    Memory:21120 kb
****************************************************************/
 
#include <bits/stdc++.h>
const int MAXN=1e5+10;
const int inf=1e9;
using namespace std;
int ch[MAXN][2],pre[MAXN],sum[MAXN],key[MAXN],lmax[MAXN],rmax[MAXN],maxx[MAXN],len[MAXN];
bool rt[MAXN];
multiset<int>smax[MAXN],s[MAXN];
multiset<int>::iterator ite;
vector<int>vec[MAXN];
void newnode(int x){
    ch[x][0]=ch[x][1]=0;pre[x]=0;sum[x]=0;key[x]=-inf;lmax[x]=rmax[x]=maxx[x]=-inf;
    rt[x]=1;len[x]=0;
}
int get_max(int x){
    if(smax[x].begin()==smax[x].end())return -inf;
    ite=smax[x].end();ite--;
    return (*ite);
}
int get_max1(int x){
    if(s[x].begin()==s[x].end())return -inf;
    ite=s[x].end();ite--;
    return (*ite);
}
int get_max2(int x){
    if(s[x].size()<2)return -inf;
    ite=s[x].end();ite--;ite--;
    return (*ite);
}
int t1,t2,t3;
void up(int x){
    t1=get_max(x);t2=get_max1(x);t3=get_max2(x);
    sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+len[x];
    maxx[x]=max(maxx[ch[x][0]],maxx[ch[x][1]]);maxx[x]=max(maxx[x],t1);
    maxx[x]=max(maxx[x],len[x]+rmax[ch[x][0]]+max(key[x],(max(t2,lmax[ch[x][1]]))));
    maxx[x]=max(maxx[x],lmax[ch[x][1]]+max(key[x],(max(t2,len[x]+rmax[ch[x][0]]))));
    maxx[x]=max(maxx[x],t2+t3);maxx[x]=max(maxx[x],t2+key[x]);
    if(key[x]==0)maxx[x]=max(maxx[x],0);
    lmax[x]=max(lmax[ch[x][0]],max(len[x]+max(t2,key[x]),lmax[ch[x][1]]+len[x])+sum[ch[x][0]]);
    rmax[x]=max(rmax[ch[x][1]],max(max(t2,key[x]),rmax[ch[x][0]]+len[x])+sum[ch[x][1]]);
}
void rotate(int x,int kind){
    int y=pre[x];
    ch[y][!kind]=ch[x][kind];pre[ch[x][kind]]=y;
    if(rt[y])rt[x]=1,rt[y]=0;
    else ch[pre[y]][ch[pre[y]][1]==y]=x;
    pre[x]=pre[y];ch[x][kind]=y;pre[y]=x;
    up(y);
}
void splay(int x){
    while(!rt[x]){
        if(rt[pre[x]])rotate(x,ch[pre[x]][0]==x);
        else{
            int y=pre[x];int kind=ch[pre[y]][0]==y;
            if(ch[y][kind]==x)rotate(x,!kind),rotate(x,kind);
            else rotate(y,kind),rotate(x,kind);
        }
    }
    up(x);
}
void access(int x){
    int y=0;
    while(x){
        splay(x);
        if(ch[x][1])rt[ch[x][1]]=1,pre[ch[x][1]]=x,smax[x].insert(maxx[ch[x][1]]),s[x].insert(lmax[ch[x][1]]);
        if(y)rt[y]=0,smax[x].erase(smax[x].lower_bound(maxx[y])),s[x].erase(s[x].lower_bound(lmax[y]));
        ch[x][1]=y;up(x);
        y=x;x=pre[x];
    }
}
void change(int x){
    access(x);splay(x);
    if(key[x]==-1*inf)key[x]=0;
    else key[x]=-1*inf;
    up(x);
}
int querty(int x){
    access(x);splay(x);
    if(maxx[x]<0)return -1;
    return maxx[x];
}
void dfs(int x,int fa){
    key[x]=0;
    for(int i=0;i<vec[x].size();i++){
        if(vec[x][i]!=fa){
            len[vec[x][i]]=1;pre[vec[x][i]]=x;dfs(vec[x][i],x);
            smax[x].insert(maxx[vec[x][i]]);s[x].insert(lmax[vec[x][i]]);
        }
    }
    up(x);
    //cout<<x<<" "<<maxx[x]<<" "<<lmax[x]<<" "<<rmax[x]<<endl;
}
char str[11];
int main(){
    int n;scanf("%d",&n);int u,v;
    for(int i=0;i<=n;i++)newnode(i);
    for(int i=1;i<n;i++)scanf("%d%d",&u,&v),vec[u].push_back(v),vec[v].push_back(u);
    dfs(1,0);
    int m;scanf("%d",&m);
    for(int i=1;i<=m;i++){
        scanf("%s",str);
        if(str[0]=='G')printf("%d\n",querty(1));
        else scanf("%d",&u),change(u);
    }
}

猜你喜欢

转载自www.cnblogs.com/wang9897/p/9545699.html