萌新刚学树剖求吊
查看原帖
萌新刚学树剖求吊
754467
f_hxr_楼主2023/10/31 17:30

rt似乎是错在树上查询?

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL maxn=1e5+7;
const LL inf=5e18+7;
LL N,M;
struct SegmentTree{
	struct Node{
		Node* ls=NULL,* rs=NULL;
		LL dat=1,Lcolor=0,Rcolor=0,setv=0;
		void DelSons(){
			if(ls)delete ls;
			if(rs)delete rs;
			ls=rs=NULL;
		}
		~Node(){DelSons();}
	}root;
	#define ls(p) p.ls
	#define rs(p) p.rs
	void pushup(Node& p){
		p.Lcolor=ls(p)->Lcolor;p.Rcolor=rs(p)->Rcolor;
		p.dat=ls(p)->dat+rs(p)->dat;
		if(ls(p)->Rcolor==rs(p)->Lcolor)p.dat--;
		if(p.dat==1)p.DelSons();
	}
	void pushdown(Node& p){
		if(!ls(p))ls(p)=new Node();
		if(!rs(p))rs(p)=new Node();
		if(p.setv!=0){
			ls(p)->Lcolor=ls(p)->Rcolor=rs(p)->Lcolor=rs(p)->Rcolor=ls(p)->setv=rs(p)->setv=p.setv;
			ls(p)->dat=rs(p)->dat=1;
			p.setv=0;
		}
	}
	void ModifyPoint(Node& p,LL L,LL R,LL inx,LL xx){
		if(L>=R){
			p.setv=p.Lcolor=p.Rcolor=xx;p.dat=1;
			return;
		}
		pushdown(p);LL mid=(L+R)>>1;
		if(inx<=mid)ModifyPoint(*ls(p),L,mid,inx,xx);
		else ModifyPoint(*rs(p),mid+1,R,inx,xx);
		pushup(p);
	}
	void ModifyPoint(LL inx,LL xx){ModifyPoint(root,1,N,inx,xx);}
	void ModifyRange(Node& p,LL L,LL R,LL ql,LL qr,LL xx){
		if(ql<=L&&R<=qr){
			p.setv=p.Lcolor=p.Rcolor=xx;p.dat=1;
			p.DelSons();
			return;
		}
		pushdown(p);LL mid=(L+R)>>1;
		if(ql<=mid)ModifyRange(*ls(p),L,mid,ql,qr,xx);
		if(mid+1<=qr)ModifyRange(*rs(p),mid+1,R,ql,qr,xx);
		pushup(p);
	}
	void ModifyRange(LL ql,LL qr,LL xx){ModifyRange(root,1,N,ql,qr,xx);}
	LL QueryRange(Node& p,LL L,LL R,LL ql,LL qr){
		if(ql<=L&&R<=qr)return p.dat;
		pushdown(p);LL mid=(L+R)>>1,ret=0;
		if(ql<=mid)ret+=QueryRange(*ls(p),L,mid,ql,qr);
		if(mid+1<=qr)ret+=QueryRange(*rs(p),mid+1,R,ql,qr);
		if(ql<=mid&&mid+1<=qr&&ls(p)->Rcolor==rs(p)->Lcolor)ret--;
		return ret;
	}
	LL QueryRange(LL ql,LL qr){return QueryRange(root,1,N,ql,qr);}
	LL QueryPoint(Node& p,LL L,LL R,LL inx){
		if(L>=R)return p.Lcolor;
		pushdown(p);LL mid=(L+R)>>1;
		if(inx<=mid)return QueryPoint(*ls(p),L,mid,inx);
		else return QueryPoint(*rs(p),mid+1,R,inx);
	}
	LL QueryPoint(LL inx){return QueryPoint(root,1,N,inx);}
};
struct ZLPF{
	LL head[maxn<<1],nxt[maxn<<1],to[maxn<<1],cnt_edge;
	LL size[maxn],fa[maxn],dep[maxn],id[maxn],Hson[maxn],Hd[maxn],dfn;
	LL val[maxn];
	SegmentTree SEG;
	void AddEdge(LL u,LL v){
		nxt[++cnt_edge]=head[u];to[cnt_edge]=v;head[u]=cnt_edge;
		nxt[++cnt_edge]=head[v];to[cnt_edge]=u;head[v]=cnt_edge;
	}
	void dfs1(LL u,LL v){
		size[u]=1;fa[u]=v;dep[u]=dep[v]+1;
		for(int i=head[u];i;i=nxt[i]){
			if(to[i]==v)continue;
			dfs1(to[i],u);size[u]+=size[to[i]];
			if(size[to[i]]>size[Hson[u]])Hson[u]=to[i];
		}
	}
	void dfs2(LL u,LL Top){
		id[u]=++dfn;Hd[u]=Top;
		if(!Hson[u])return;dfs2(Hson[u],Top);
		for(int i=head[u];i;i=nxt[i]){
			if(to[i]==fa[u]||to[i]==Hson[u])continue;
			dfs2(to[i],to[i]);
		}
	}
	void init(){
		scanf("%lld%lld",&N,&M);
		for(int i=1;i<=N;i++)scanf("%lld",&val[i]);
		for(int i=1;i<N;i++){
			LL u,v;scanf("%lld%lld",&u,&v);
			AddEdge(u,v);
		}
		dfs1(1,0);dfs2(1,1);
		for(int i=1;i<=N;i++)SEG.ModifyPoint(id[i],val[i]);
	}
	void ModifyRangeOnTree(LL u,LL v,LL xx){
		while(Hd[u]!=Hd[v]){
			if(dep[Hd[u]]<dep[Hd[v]])swap(u,v);
			SEG.ModifyRange(id[Hd[u]],id[u],xx);
			u=fa[Hd[u]];
		}
		if(dep[u]<dep[v])swap(u,v);
		SEG.ModifyRange(id[v],id[u],xx);
	}
	LL QueryRangeOnTree(LL u,LL v){
		LL ret=0,Ucolor=-1,Vcolor=-1;
		while(Hd[u]!=Hd[v]){
			if(dep[Hd[u]]<dep[Hd[v]]){
				ret+=SEG.QueryRange(id[Hd[v]],id[v]);
				LL NowColor=SEG.QueryPoint(id[v]);
				if(NowColor==Vcolor)ret--;
				Vcolor=SEG.QueryPoint(id[Hd[v]]); 
				v=fa[Hd[v]];	
			}else{
				ret+=SEG.QueryRange(id[Hd[u]],id[u]);
				LL NowColor=SEG.QueryPoint(id[u]);
				if(NowColor==Ucolor)ret--;
				Ucolor=SEG.QueryPoint(id[Hd[u]]); 
				u=fa[Hd[u]];
			}
		}
		if(dep[u]<dep[v]){
			ret+=SEG.QueryRange(id[u],id[v]);
			LL NowColor=SEG.QueryPoint(id[v]);
			if(NowColor==Ucolor||NowColor==Vcolor)ret--;
		}else{
			ret+=SEG.QueryRange(id[v],id[u]);
			LL NowColor=SEG.QueryPoint(id[u]);
			if(NowColor==Ucolor||NowColor==Vcolor)ret--;
		}
		return ret;
	}
	void Query(){
		for(int i=1;i<=M;i++){
			char op;
			LL u,v,color;
			cin>>op;
			if(op=='C'){
				cin>>u>>v>>color;
				ModifyRangeOnTree(u,v,color);
			}
			else if(op=='Q'){
				cin>>u>>v;
				printf("%lld\n",QueryRangeOnTree(u,v));
			}
		}
	}
}Tree;
int main(){
	//freopen("P2846.in","r",stdin);
	//freopen("P2846.ans","w",stdout);
	Tree.init();Tree.Query();
	return 0;
}
2023/10/31 17:30
加载中...