zoukankan      html  css  js  c++  java
  • B

    题目链接:猛戳这里

    题目大意:给一棵多叉树,初始值都为0,o x为翻转以x为根的子树,q x为查询以x为根的子树有多少个1

    思路:这数据范围,暴力是不行的,怎么暴力都是不行的>_<。这题的要求是:修改一大片、查询一大片,比较容易想到的就是线段树(树状 数组也可以,不过要翻转嘛……好像有难度……反正我不会>_<)。问题是这玩意儿怎么转换成线段树呢?要转化成线段树,就要把每个点的子孙们 都放到一片连续的空间里。这时,若使用DFS,遍历的顺序刚刚好符合要求,于是我们就DFSo(∩_∩)o 。DFS途中就可以算出每个点的及其子孙覆盖的区域。然后变成线段树之后呢,随便搞搞就行了o(∩_∩)o

    AC Code:

      1 #include <cstdio>
      2 #include <cstring>
      3 
      4 const int MAX = 100010;
      5 
      6 int flip[MAX*4], sum[MAX*4], cnt[MAX*4];//tree
      7 int head[MAX], next[MAX], to[MAX], ecnt;
      8 int beg[MAX], size[MAX], dfs_clock;
      9 int y1, y2;
     10 
     11 void tle() {while(1) ;}
     12 
     13 void init() {
     14     ecnt = 1;
     15     dfs_clock = 0;
     16     memset(head, 0, sizeof(head));
     17     memset(flip, 0, sizeof(flip));
     18     memset(cnt, 0, sizeof(cnt));
     19 }
     20 
     21 void add_edge(int u, int v) {
     22     to[ecnt] = v; next[ecnt] = head[u]; head[u] = ecnt++;
     23 }
     24 
     25 void dfs(int x) {
     26     size[x] = 1;
     27     beg[x] = ++dfs_clock;
     28     for(int p = head[x]; p; p = next[p]) {
     29         dfs(to[p]);
     30         size[x] += size[to[p]];
     31     }
     32 }
     33 
     34 void maintain(int x, int l, int r) {
     35     int lc = x * 2, rc = x * 2 + 1;
     36     if(l < r) {
     37         cnt[x] = cnt[rc] + cnt[lc];
     38     }
     39 }
     40 
     41 void pushdown(int x) {
     42     int lc = x * 2, rc = x * 2 + 1;
     43     if(flip[x]) {
     44         flip[x] = 0;
     45         flip[lc] ^= 1;
     46         cnt[lc] = sum[lc] - cnt[lc];
     47         flip[rc] ^= 1;
     48         cnt[rc] = sum[rc] - cnt[rc];
     49     }
     50 }
     51 
     52 void update(int x, int l, int r) {
     53     int lc = x * 2, rc = x * 2 + 1;
     54     if(y1 <= l && r <= y2) {
     55         flip[x] ^= 1;
     56         cnt[x] = sum[x] - cnt[x];
     57     }
     58     else {
     59         pushdown(x);
     60         int mid = (l + r) / 2;
     61         if(y1 <= mid) update(lc, l, mid);
     62         if(mid < y2) update(rc, mid + 1, r);
     63         maintain(x, l, r);
     64     }
     65 }
     66 
     67 int ans;
     68 
     69 void query(int x, int l, int r) {
     70     int lc = x * 2, rc = x * 2 + 1;
     71     if(y1 <= l && r <= y2) ans += cnt[x];
     72     else {
     73         pushdown(x);
     74         int mid = (l + r) / 2;
     75         if(y1 <= mid) query(lc, l, mid);
     76         if(mid < y2) query(rc, mid + 1, r);
     77     }
     78 }
     79 
     80 void build(int x, int l, int r) {
     81     int lc = x * 2, rc = x * 2 + 1;
     82     if(l == r) {
     83         sum[x] = 1;
     84     }
     85     else {
     86         int mid = (l + r) / 2;
     87         build(lc, l, mid);
     88         build(rc, mid + 1, r);
     89         sum[x] = sum[lc] + sum[rc];
     90     }
     91 }
     92 
     93 int main() {
     94     int n, m, x;
     95     char c[2];
     96     while(scanf("%d%d", &n, &m) != EOF) {
     97         init();
     98         for(int i = 2; i <= n; ++i) {
     99             scanf("%d", &x);
    100             add_edge(x, i);
    101         }
    102         dfs(1);
    103         build(1, 1, n);
    104         while(m--) {
    105             scanf("%s%d", c, &x);
    106             y1 = beg[x]; y2 = beg[x] + size[x] - 1;
    107             if(c[0] == 'o') {
    108                 update(1, 1, n);
    109             }
    110             if(c[0] == 'q') {
    111                 ans = 0;
    112                 query(1, 1, n);
    113                 printf("%d
    ", ans);
    114             }
    115         }
    116         puts("");
    117     }
    118 }

    By Oyking

  • 相关阅读:
    codevs 2149 矩形周长
    codevs 3044 矩形面积求并
    codevs 1293 送给圣诞夜的极光
    codevs 2806 红与黑
    codevs 1536 海战
    codevs 1262 不要把球传我
    codevs 2606 约数和问题
    BZOJ 2301 problem b
    BZOJ 3994 约数个数和
    codevs 1173 最优贸易
  • 原文地址:https://www.cnblogs.com/scnuacm/p/3226691.html
Copyright © 2011-2022 走看看