树点涂色
?
?我們定義f(x),表示x與fa[x]的顏色是否相同,相同為0,不同為1,令 f(1)=1。g(x)表示x到root路徑上的f的和。然后考慮怎么維護g(x)。?
?對于操作1,用LCT中的access操作來維護。
對于操作2,直接線段樹查詢。
對于操作3,維護一個最大值,然后區間查詢最大值就可以了。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define N 400010 using namespace std; int point[N],nxt[N],v[N],tr[N],delta[N],l[N],r[N],deep[N],mi[20]; int n,m,k,col[N],f[N][20],fa[N],ch[N][3],tot,sz,pos[N],cur[N]; void add(int x,int y){tot++;nxt[tot]=point[x];point[x]=tot;v[tot]=y;tot++;nxt[tot]=point[y];point[y]=tot;v[tot]=x; } void dfs(int rt){int x=rt; while (true) {if (!deep[x]) {deep[x]=deep[f[x][0]]+1; for (int i=1;i<=17;i++) {if (deep[x]-mi[i]<0) break;f[x][i]=f[f[x][i-1]][i-1];}l[x]=r[x]=++sz; pos[sz]=x; cur[x]=point[x];}bool pd=false;for (int i=cur[x];i;i=nxt[i]) {cur[x]=nxt[i];if (v[i]!=f[x][0]) {f[v[i]][0]=fa[v[i]]=x; x=v[i]; pd=true;break;}}if (!pd) {int t=f[x][0];// cout<<t<<endl;r[t]=max(r[t],r[x]);if (x==rt) break;x=t;}} } int lca(int x,int y){if (deep[x]<deep[y]) swap(x,y);int k=deep[x]-deep[y];for (int i=0;i<=17;i++)if ((k>>i)&1) x=f[x][i];if (x==y) return x;for (int i=17;i>=0;i--)if (f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];return f[x][0]; } void update(int now){tr[now]=max(tr[now<<1],tr[now<<1|1]); } void pushdown(int now){if (delta[now]) {tr[now<<1]+=delta[now]; tr[now<<1|1]+=delta[now];delta[now<<1]+=delta[now]; delta[now<<1|1]+=delta[now];delta[now]=0;} } void change(int now,int l,int r,int ll,int rr,int val){if (ll<=l&&r<=rr) {tr[now]+=val; delta[now]+=val;return;}int mid=(l+r)/2; pushdown(now);if (ll<=mid) change(now<<1,l,mid,ll,rr,val);if (rr>mid) change(now<<1|1,mid+1,r,ll,rr,val);update(now); } int find(int now,int l,int r,int x){if (l==r) return tr[now];int mid=(l+r)/2;pushdown(now);if (x<=mid) return find(now<<1,l,mid,x);else return find(now<<1|1,mid+1,r,x); } int query(int now,int l,int r,int ll,int rr){if (ll<=l&&r<=rr) return tr[now];int mid=(l+r)/2; int ans=0;pushdown(now);if (ll<=mid) ans=max(ans,query(now<<1,l,mid,ll,rr));if (rr>mid) ans=max(ans,query(now<<1|1,mid+1,r,ll,rr));return ans;} bool isroot(int x){return ch[fa[x]][1]!=x&&ch[fa[x]][0]!=x; } int get(int x){return ch[fa[x]][1]==x; } void rotate(int x){int y=fa[x]; int z=fa[y]; int which=get(x);if (!isroot(y)) ch[z][ch[z][1]==y]=x;fa[x]=z; fa[y]=x; ch[y][which]=ch[x][which^1];fa[ch[x][which^1]]=y; ch[x][which^1]=y; } void splay(int x){int y;while (!isroot(x)){y=fa[x];if (!isroot(y)) rotate(get(y)==get(x)?y:x);rotate(x);} } int get_root(int x){while (ch[x][0]) x=ch[x][0];return x; } void access(int x){int t=0;while (x) {col[x]=k;splay(x);int t1=get_root(ch[x][1]);if (t1) change(1,1,n,l[t1],r[t1],1);ch[x][1]=t;int t2=get_root(t);if (t2) change(1,1,n,l[t2],r[t2],-1);t=x; x=fa[x];} } int main(){scanf("%d%d",&n,&m); k=n; mi[0]=1;for (int i=1;i<=18;i++) mi[i]=mi[i-1]*2;for (int i=1;i<n;i++) {int x,y; scanf("%d%d",&x,&y);add(x,y);}dfs(1);for (int i=1;i<=n;i++) change(1,1,n,l[i],r[i],1);for (int i=1;i<=m;i++) {int opt,x,y; scanf("%d%d",&opt,&x);if (opt==1) k++,access(x);if (opt==2) {scanf("%d",&y); int t=lca(x,y);printf("%d\n",find(1,1,n,l[x])+find(1,1,n,l[y])-2*find(1,1,n,l[t])+1);}if (opt==3) printf("%d\n",query(1,1,n,l[x],r[x]));} }?
轉載于:https://www.cnblogs.com/harden/p/6701749.html
總結
- 上一篇: JAVA与模式
- 下一篇: 170405、java版MD5工具类