《洛谷-2146》
思路:
观察后可以发现。
卸载操作就是删除子树上存在的点(包括自身).
安装操作就是添加上该点到根的链上的所有点。
树剖重链,线段树维护重链。
对于卸载很简单,删去子树上的值即可。
对于安装。不断跳到链头,直到到根即可。
对于查询有多少只改变了。
只需要记录改变前的值,然后查询改变后的值。
一减就是。
常数比较大。
用上快读,链式前向星。
Code:
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<int,int> pii; const int N = 2e5+5; const int M = 1e6+5; const int Mod = 1e9+7; #define pi acos(-1) #define INF 1e18 #define INM INT_MIN #define rg register #define pb(a) push_back(a) #define mk(a,b) make_pair(a,b) #define dbg(x) cout << "now this num is " << x << endl; #define met0(axx) memset(axx,0,sizeof(axx)); #define metf(axx) memset(axx,-1,sizeof(axx)); #define sd(ax) scanf("%d",&ax) #define sld(ax) scanf("%lld",&ax) #define sldd(ax,bx) scanf("%lld %lld",&ax,&bx) #define sdd(ax,bx) scanf("%d %d",&ax,&bx) #define sddd(ax,bx,cx) scanf("%d %d %d",&ax,&bx,&cx) #define sfd(ax) scanf("%lf",&ax) #define sfdd(ax,bx) scanf("%lf %lf",&ax,&bx) #define pr(a) printf("%d\n",a) #define plr(a) printf("%lld\n",a) /* 卸载操作:删除子树上的所有节点。 安装操作:查询当前链,然后跳到链头。继续直到根. */ int n,cnt = 0,num = 0; struct Node{int L,r,sum,tag;}node[N<<2]; struct XO{int to,next;}e[N<<1]; int dep[N],id[N],rk[N],fa[N],ssize[N],son[N],top[N],head[N]; inline int read() { int x = 0,f = 1;char c = getchar(); while(c < '0' || c > '9') {if(c == '-') f = -1;c = getchar();} while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();} return x*f; } inline void add(int u,int v) { e[++num].to = v,e[num].next = head[u],head[u] = num; } void dfs(int u,int ffa) { fa[u] = ffa; dep[u] = dep[ffa]+1; ssize[u] = 1; for(int i = head[u];i;i = e[i].next) { int v = e[i].to; if(v == ffa) continue; dfs(v,u); ssize[u] += ssize[v]; if(ssize[v] > ssize[son[u]]) son[u] = v; } } void dfs1(int u,int sta) { id[u] = ++cnt; rk[cnt] = u; top[u] = sta; if(son[u] == -1) return ; dfs1(son[u],sta); for(int i = head[u];i;i = e[i].next) { int v = e[i].to; if(v != fa[u] && v != son[u]) dfs1(v,v);//重儿子已经连过. } } void Pushup(int idx){node[idx].sum = node[idx<<1].sum + node[idx<<1|1].sum;} void Pushdown(int idx) { if(node[idx].tag != 0) { int tag = node[idx].tag; if(tag == -1) { node[idx<<1].sum = node[idx<<1|1].sum = 0; node[idx<<1].tag = node[idx<<1|1].tag = -1; } if(tag == 1) { node[idx<<1].sum = (node[idx<<1].r-node[idx<<1].L+1); node[idx<<1|1].sum = (node[idx<<1|1].r-node[idx<<1|1].L+1); node[idx<<1].tag = node[idx<<1|1].tag = 1; } node[idx].tag = 0; } } void build(int L,int r,int idx) { node[idx].L = L,node[idx].r = r,node[idx].tag = 0; if(L == r) { node[idx].sum = 0; return ; } int mid = (L+r)>>1; build(L,mid,idx<<1); build(mid+1,r,idx<<1|1); Pushup(idx); } void update(int L,int r,int idx,int k)//k-1-安装,k-0-卸载 { if(node[idx].L >= L && node[idx].r <= r) { if(k == 0) node[idx].sum = 0,node[idx].tag = -1; else node[idx].sum = (node[idx].r-node[idx].L+1),node[idx].tag = 1; } else { Pushdown(idx); int mid = (node[idx].L+node[idx].r)>>1; if(mid >= L) update(L,r,idx<<1,k); if(mid < r) update(L,r,idx<<1|1,k); Pushup(idx); } } int query(int L,int r,int idx) { if(node[idx].L >= L && node[idx].r <= r) return node[idx].sum; int mid = (node[idx].L+node[idx].r)>>1,ans = 0; Pushdown(idx); if(mid >= L) ans += query(L,r,idx<<1); if(mid < r) ans += query(L,r,idx<<1|1); return ans; } int Tree_cut(int x) { int ans = 0,xx = x,tmp = 0; while(xx != fa[0]) { ans += query(id[top[xx]],id[xx],1); update(id[top[xx]],id[xx],1,1); xx = fa[top[xx]]; } while(x != fa[0]) { tmp += query(id[top[x]],id[x],1); x = fa[top[x]]; } return tmp-ans; } void run() { n = read(); for(int i = 0;i < n;++i) son[i] = -1;//0为根 for(int i = 1;i < n;++i) { int x;x = read(); add(x,i),add(i,x); } dfs(0,-1); dfs1(0,0); build(1,cnt,1); int q;sd(q); while(q--) { string s;int ma; cin >> s;ma = read(); if(s == "install") { int ans = Tree_cut(ma); pr(ans); } else { int ans = query(id[ma],id[ma]+ssize[ma]-1,1); pr(ans); update(id[ma],id[ma]+ssize[ma]-1,1,0); } } } int main() { run(); system("pause"); return 0; }