《洛谷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;
}
原文地址:https://www.cnblogs.com/zwjzwj/p/13163268.html