SP16580 QTREE7 - Query on a tree VII
阿新 • • 發佈:2018-07-15
multi 會有 != ons build spl esp 需要 方法 ,不能支持加減操作,所以用一個 \(set\) 或 堆來維護就行了
Description
一棵樹,每個點初始有個點權和顏色(0/1) 0 u :詢問所有u,v 路徑上的最大點權,要滿足u,v 路徑上所有點的顏色都相同 1 u :反轉u 的顏色 2 u w :把u 的點權改成w
Solution
對於每一種顏色,我們開一個 \(LCT\) 來維護
首先為了使得 \(LCT\) 維護的黑樹連通,難免會有白點,但是最多只會有一個,因為一旦不連通了就沒有必要維護了,對於白樹也是同理
對於每一個 \(LCT\) 的節點,只需要維護一個 \(splay\) 中的子樹 \(max\) 和虛子樹的 \(max\) 就行了,和平時的 \(LCT\) 維護虛子樹的方法相同,只需要把虛子樹的答案當作這個點的權值就好了,唯一不同的是,這個題是維護 \(max\)
一個細節:
對於一個連通塊,可能根節點是不同色點,對於詢問那麽就需要加一個特判:
如果是根節點不同色的,答案就是右子樹的答案
否則就是根節點的答案
#include<bits/stdc++.h> using namespace std; const int N=1e5+10; int pa[N],n,Q,head[N],nxt[N*2],to[N*2],num=0,c[N]; struct lxt{ int fa[N],ch[N][2],v[N],w[N]; multiset<int>S[N]; inline bool isrt(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;} inline void upd(int x){ v[x]=w[x]; if(!S[x].empty())v[x]=max(v[x],*--S[x].end()); if(ch[x][0])v[x]=max(v[x],v[ch[x][0]]); if(ch[x][1])v[x]=max(v[x],v[ch[x][1]]); } inline void rotate(int x){ int y=fa[x];bool t=(ch[y][1]==x); ch[y][t]=ch[x][!t]; fa[ch[y][t]]=y; ch[x][!t]=y; fa[x]=fa[y]; if(!isrt(y))ch[fa[y]][ch[fa[y]][1]==y]=x; fa[y]=x;upd(y);upd(x); } inline void splay(int x){ while(!isrt(x)){ int y=fa[x],p=fa[y]; if(isrt(y))rotate(x); else if((ch[p][0]==y)==(ch[y][0]==x))rotate(y),rotate(x); else rotate(x),rotate(x); } } inline void access(int x){ int y=0; while(x){ splay(x); if(ch[x][1])S[x].insert(v[ch[x][1]]); if(y)S[x].erase(S[x].find(v[y])); ch[x][1]=y;upd(x);x=fa[y=x]; } } inline int query(int x){ int co=c[x]; access(x);splay(x); while(ch[x][0])x=ch[x][0]; splay(x); return co==c[x]?v[x]:v[ch[x][1]]; } inline void cut(int x){ if(!pa[x])return ; access(x);splay(x);fa[ch[x][0]]=0;ch[x][0]=0;upd(x); } inline void link(int x){ if(!pa[x])return ; access(pa[x]);splay(pa[x]);splay(x); ch[pa[x]][1]=x;fa[x]=pa[x];upd(pa[x]); } }tr[2]; inline void link(int x,int y){nxt[++num]=head[x];to[num]=y;head[x]=num;} inline void build(int x,int last){ for(int u,i=head[x];i;i=nxt[i]){ if((u=to[i])==last)continue; build(u,x);pa[u]=x; tr[c[u]].fa[u]=x;tr[c[u]].S[x].insert(tr[c[u]].v[u]); }tr[0].upd(x);tr[1].upd(x); } int main(){ freopen("pp.in","r",stdin); freopen("pp.out","w",stdout); cin>>n; int x,y,op; for(int i=1;i<n;i++){ scanf("%d%d",&x,&y); link(x,y);link(y,x); } for(int i=1;i<=n;i++)scanf("%d",&c[i]); for(int i=1;i<=n;i++)scanf("%d",&tr[0].w[i]),tr[1].w[i]=tr[0].w[i]; build(1,0); cin>>Q; while(Q--){ scanf("%d%d",&op,&x); if(op==0)printf("%d\n",tr[c[x]].query(x)); else if(op==1){ tr[c[x]].cut(x);tr[c[x]^1].link(x); c[x]^=1; } else { scanf("%d",&y); tr[0].access(x);tr[0].splay(x); tr[1].access(x);tr[1].splay(x); tr[0].w[x]=tr[1].w[x]=y; tr[0].upd(x);tr[1].upd(x); } } return 0; }
SP16580 QTREE7 - Query on a tree VII