• [NOI2015]软件包管理器 树链剖分


    ~~~题面~~~

    题解:

    首先我们观察到0号不会依赖别人,而其他的软件都会依赖且仅会依赖一个软件。因此这是一棵树。

    于是我们在看看要支持一些什么操作。

    1,安装一个软件要改变多少软件的状态。

      如果将一个软件与所依赖的软件相连,那么可能要改变的状态就是它自己和往上走直到根的那条链上的点。

    2,卸载一个软件要改变多少软件的状态

      显然是自己+子树。

    那么我们可以想到什么呢?

    树链剖分!

    安装就查询从自己往上走的点中有多少已经被安装。

    deep[x](deep[0] = 1)就是可能要改变的软件数,假设已经有k个被安装,那么要改变的软件数就是deep[x] - k

    卸载就查询子树+自己中有多少已经安装了的,这个数量就是答案。

    每次安装查询时都把查询的点赋为1,卸载时把所有涉及到的点赋为0,线段树维护

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define R register int
      4 #define AC 120000
      5 #define ac 600000//error ...所以说还是数组小了的锅么
      6 #define D printf("line in %d
    ", __LINE__);
      7 int n, m, cnt, ans, w;
      8 int date[AC], Next[AC], Head[AC], tot;//因为是树,所以只要开这么大
      9 int son[AC], top[AC], father[AC], deep[AC], Size[AC], id[AC];
     10 int tree[ac], l[ac], r[ac], lazy[ac];//线段树开4倍吧
     11 char s[30];
     12 
     13 inline int read()
     14 {
     15     int x = 0; char c = getchar();
     16     while(c > '9' || c < '0') c = getchar();
     17     while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();//error !!! 读入优化写错了。。。。
     18     return x;
     19 }
     20 
     21 inline void add(int f, int w)
     22 {
     23     date[++tot] = w, Next[tot] = Head[f], Head[f] = tot;
     24 }
     25 
     26 void pre()//读入依赖关系, 因为编号从0开始, 所以整体往后顺延一个
     27 {
     28     n = read();//序号全部往后推一个, 但总数又不会变,,,,
     29     for(R i=2;i<=n;i++)
     30     {
     31         father[i] = read() + 1;
     32         add(father[i], i);
     33     }
     34     deep[1] = 1;
     35 }
     36 //Size包括自己
     37 void dfs1(int x)//get son && Size && deep
     38 {
     39     int maxson = 0, now;
     40     Size[x] = 1;//先加上自己
     41     for(R i = Head[x]; i ; i = Next[i])
     42     {
     43         now = date[i];
     44         if(now == father[x]) continue;
     45         deep[now] = deep[x] + 1;
     46         dfs1(now);
     47         Size[x] += Size[now];
     48         if(Size[now] > Size[maxson]) maxson = now;
     49     }
     50     son[x] = maxson;
     51 }
     52 
     53 void dfs2(int x, int topx)//get top && id
     54 {
     55     int now;
     56     id[x] = ++cnt;
     57     top[x] = topx;
     58     if(!son[x]) return ;
     59     dfs2(son[x], topx);//继承top
     60     for(R i = Head[x]; i ; i = Next[i])
     61     {
     62         now = date[i];
     63         if(now == father[x] || now == son[x]) continue;//这两个都是不能去的
     64         dfs2(now, now);//新开
     65     }
     66 }
     67 
     68 void build(int x, int ll, int rr)
     69 {
     70     l[x] = ll, r[x] = rr;
     71     if(ll == rr) return ;//...调试没删
     72     int mid = (ll + rr) >> 1;
     73     build(x * 2, ll, mid);
     74     build(x * 2 + 1, mid + 1, rr); 
     75 }
     76 
     77 inline void update(int x)
     78 {
     79     int ll = x * 2, rr = ll + 1;
     80     lazy[ll] = lazy[rr] = lazy[x];
     81     tree[ll] = (r[ll] - l[ll] + 1) * (lazy[x] - 1);//要么全为0,要么全为1
     82     tree[rr] = (r[rr] - l[rr] + 1) * (lazy[x] - 1);//为了方便判断
     83     lazy[x] = 0;//下传标记之后要清0
     84 }//1 表示 0, 2 表示1,所以用的时候要-1
     85 
     86 void search(int x, int ll, int rr)
     87 {
     88     if(lazy[x]) update(x);
     89     if(ll == l[x] && rr == r[x]) 
     90     {
     91         ans -= tree[x];
     92         return ;
     93     }
     94     else
     95     {
     96         int mid = (l[x] + r[x]) >> 1;
     97         if(ll > mid) search(x * 2 + 1, ll, rr);
     98         else if(rr <= mid) search(x * 2, ll, rr);
     99         else
    100         {
    101             search(x * 2, ll, mid);
    102             search(x * 2 + 1, mid + 1, rr);
    103         } 
    104     }
    105 }
    106 
    107 void change(int x, int ll, int rr)
    108 {
    109     if(l[x] == ll && r[x] == rr) 
    110     {
    111         lazy[x] = w;
    112         tree[x] = (r[x] - l[x] + 1) * (w - 1); 
    113     } 
    114     else
    115     {
    116         int mid = (l[x] + r[x]) >> 1;
    117         if(ll > mid) change(x * 2 + 1, ll, rr);
    118         else if(rr <= mid) change(x * 2, ll, rr);
    119         else
    120         {
    121             change(x * 2, ll, mid);
    122             change(x * 2 + 1, mid + 1, rr);
    123         } 
    124         tree[x] = tree[x * 2] + tree[x * 2 + 1];//因为是直接修改,而不是加减,所以在这里修改tree[x]的值 
    125     }
    126 }
    127 
    128 void install(int x)
    129 {
    130     ans = deep[x];
    131     w = 2;//改为1(这里2代表1)
    132     while(x)//father[top[1]] = 0;
    133     {
    134         search(1, id[top[x]], id[x]);
    135         change(1, id[top[x]], id[x]);
    136         x = father[top[x]];
    137     }
    138     printf("%d
    ", ans);
    139 }
    140 
    141 void uninstall(int x)
    142 {
    143     ans = 0;
    144     search(1, id[x], id[x] + Size[x] - 1);
    145     w = 1;
    146     change(1, id[x], id[x] + Size[x] - 1);                                                                                        
    147     printf("%d
    ", -ans);//因为默认是减,所以直接求的话会是相反数
    148 }
    149 
    150 void work()//读入询问
    151 {
    152     int a;
    153     m = read();
    154     //scanf("%d", &m);
    155     for(R i = 1; i <= m; i++)
    156     {
    157         scanf("%s", s + 1);
    158     //    printf("%d: ", i);
    159     //    printf("%d ", l[7424]);
    160         //b = i;//辅助watch
    161         a = read() + 1;
    162         if(s[1] == 'i') install(a);//安装
    163         else uninstall(a);
    164     }
    165 }
    166 
    167 int main()
    168 {
    169 //    freopen("in.in", "r", stdin);
    170     pre();
    171     dfs1(1);
    172     dfs2(1, 1);
    173     build(1, 1, n);
    174     work();
    175 //    fclose(stdin);
    176     return 0;
    177 }
  • 相关阅读:
    Open vSwitch 工作原理
    网络虚拟化技术(二): TUN/TAP MACVLAN MACVTAP
    网络虚拟化技术(一): Linux网络虚拟化
    linux中diff命令用法
    linux中comm命令用法
    获取SHA1和MD5
    ImageView显示网络图片
    API23时权限不被许可
    Unable to add window -- token null is not for an application
    Unable to locate player settings. bin/Data/settings.xml
  • 原文地址:https://www.cnblogs.com/ww3113306/p/9249781.html
Copyright © 2020-2023  润新知