zoukankan      html  css  js  c++  java
  • 《洛谷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;
    }
  • 相关阅读:
    Flume
    nodejs中npm工具自身升级
    Nodejs v4.x.0API文档学习(1)简介
    nodejs设置NODE_ENV环境变量(1)
    nodejs使用express4框架默认app.js配置说明
    mongodb2.X添加权限
    javascript中new Date浏览器兼容性处理
    Android Studio中文组(中文社区)
    Javascript日期处理类库Moment.js
    android 按两次返回键退出应用
  • 原文地址:https://www.cnblogs.com/zwjzwj/p/13163268.html
Copyright © 2011-2022 走看看