• bzoj4196: [Noi2015]软件包管理器(树链剖分)


    bzoj4196

    太久没写树剖都忘了,赶紧来写写。

    题目描述:有n个软件,每个软件都有一个且仅有一个依赖关系,只有安装了依赖的软件才能安装这个软件。0节点没有依赖关系。

                      给定q个询问,每个询问为安装或卸载某个软件,问每次询问会改变多少个软件的安装状态。

    输入格式:第一行一个整数表示n。

                     第二行第i个表示第i个软件的依赖软件。

                     第三行一个整数q,表示询问的个数。

                     接下来q行每行一个询问,install x 表示安装编号为 x 的软件。uninstall x 表示卸载编号为 x 的软件。

    输出格式:每个询问,输出一个整数,表示会改变的软件状态。

    输入样例:

    7
    0 0 0 1 1 5
    5
    install 5
    install 6
    uninstall 1
    install 4
    uninstall 0

    输出样例:

    3
    1
    3
    2
    3

    解析:一道树剖的模板题,用0表示没有安装,用1表示安装了。每次安装操作就输出dep[x] - x到根节点的1的个数,再将根节点到 x 变为1。

              卸载时就询问 x 的子树中1的个数,再全部改为0即可。因为 x 的子树中的dfs序是连续的,所以直接用子树的大小就可以知道在线段树上的标号。

    代码如下:

      1 #include<cstdio>
      2 #include<vector>
      3 #include<algorithm>
      4 #include<cstring>
      5 #define lc o << 1
      6 #define rc o << 1 | 1
      7 using namespace std;
      8 
      9 const int maxn = 1e5 + 5;
     10 int n, bj[maxn * 4], sum[maxn * 4], q;
     11 int dfn[maxn], cnt, dep[maxn], fa[maxn], seq[maxn], size[maxn], heavy[maxn], top[maxn];
     12 char s[15];
     13 vector <int> ve[maxn];
     14 
     15 int read(void) {
     16     char c; while (c = getchar(), c < '0' || c >'9'); int x = c - '0';
     17     while (c = getchar(), c >= '0' && c <= '9') x = x * 10 + c - '0'; return x;
     18 }
     19 
     20 void dfs1(int u, int pre) {
     21     dep[u] = dep[pre] + 1;
     22     fa[u] = pre; size[u] = 1;
     23       for (int i = 0; i < ve[u].size(); ++ i) {
     24           int v = ve[u][i];
     25             if (v == pre) continue;
     26           dfs1(v, u);
     27           size[u] += size[v];
     28             if (size[v] > size[heavy[u]]) heavy[u] = v;
     29       } 
     30 }
     31 
     32 void dfs2(int u, int cur) {
     33     top[u] = cur; dfn[u] = ++ cnt; 
     34     seq[cnt] = u; //seq对这题好像没什么用,但还是打了 QAQ 
     35       if (!heavy[u]) return;
     36     dfs2(heavy[u], cur);
     37       for (int i = 0; i < ve[u].size(); ++ i) {
     38           int v = ve[u][i];
     39             if (v == fa[u] || v == heavy[u]) continue;
     40           dfs2(v, v);
     41       }
     42 }
     43 
     44 void pushdown(int o, int l, int r) {
     45     int mid = l + r >> 1;
     46     sum[lc] = bj[o] * (mid - l + 1);
     47     sum[rc] = bj[o] * (r - mid);
     48     bj[lc] = bj[rc] = bj[o]; bj[o] = -1;
     49 }
     50 
     51 void modify(int o, int l, int r, int ql, int qr, int c) {
     52     if (ql <= l && qr >= r) {
     53       sum[o] = c * (r - l + 1); bj[o] = c;
     54       return;
     55     }
     56     int mid = l + r >> 1;
     57     if (bj[o] != -1) pushdown(o, l, r);
     58     if (ql <= mid) modify(lc, l, mid, ql, qr, c);
     59     if (qr > mid) modify(rc, mid + 1, r, ql, qr, c);
     60     sum[o] = sum[lc] + sum[rc];
     61 }
     62 
     63 int query(int o, int l, int r, int ql, int qr) {
     64     if (ql <= l && qr >= r) return sum[o];
     65     int mid = l + r >> 1, ans = 0;
     66     if (bj[o] != -1) pushdown(o, l, r);
     67     if (ql <= mid) ans += query(lc, l, mid, ql, qr);
     68     if (qr > mid) ans += query(rc, mid + 1, r, ql, qr);
     69     return ans;
     70 }
     71 
     72 void chain_modify(int x, int y, int c) {
     73     int fax = top[x], fay = top[y];
     74       while (fax != fay) {
     75           if (dep[fax] < dep[fay]) {
     76               swap(fax, fay);
     77               swap(x, y);
     78           }
     79         modify(1, 1, n, dfn[fax], dfn[x], c);
     80         x = fa[fax];
     81         fax = top[x];
     82       }
     83       if (dep[x] > dep[y]) swap(x, y);
     84     modify(1, 1, n, dfn[x], dfn[y], c);
     85 }
     86 
     87 int chain_query(int x, int y) {
     88     int fax = top[x], fay = top[y], ans = 0;
     89       while (fax != fay) {
     90           if (dep[fax] < dep[fay]) {
     91               swap(fax, fay);
     92               swap(x, y);
     93           }
     94         ans += query(1, 1, n, dfn[fax], dfn[x]);
     95         x = fa[fax];
     96         fax = top[x];
     97       }
     98       if (dep[x] > dep[y]) swap(x, y);
     99     ans += query(1, 1, n, dfn[x], dfn[y]);
    100     return ans;
    101 }
    102 
    103 int main() {
    104     n = read(); 
    105       for (int i = 2; i <= n; ++ i) {
    106           int x = read() + 1;
    107           ve[x].push_back(i);
    108           ve[i].push_back(x);
    109       }
    110     q = read();
    111     dfs1(1, 0);
    112     dfs2(1, 1);
    113     memset(bj, -1, sizeof(bj));
    114       while (q --) {
    115           scanf("%s", s + 1);
    116           int x = read() + 1;
    117             if (s[1] == 'i') {
    118                   int ans = dep[x] - chain_query(1, x);
    119                   if (ans < 0) {
    120                           ans = ans;
    121                           ans = chain_query(1, x);
    122                   }
    123                   printf("%d
    ", dep[x] - chain_query(1, x));
    124                   chain_modify(1, x, 1);
    125             }
    126           else {
    127               printf("%d
    ", query(1, 1, n, dfn[x], dfn[x] + size[x] - 1)); //直接用size算出子树中节点的dfs序最大值 
    128               modify(1, 1, n, dfn[x], dfn[x] + size[x] - 1, 0);
    129           }
    130       }
    131     return 0;
    132 }
  • 相关阅读:
    c++之输出文件和输入文件的处理
    C++之输入输出流
    c++之虚析构函数
    c++之虚函数和基类指针
    接口自动化测试框架Karate入门
    uiautomator+cucumber实现移动app自动化测试
    calabash-android Win10 入门笔记
    Page Object 模式编写UiAutomator脚本
    ruby脚本打印日志到rspec的报告文件中
    Ruby跳出多层循环 catch...throw
  • 原文地址:https://www.cnblogs.com/Gaxc/p/9927063.html
Copyright © 2020-2023  润新知