zoukankan      html  css  js  c++  java
  • ZOJ 3686 A Simple Tree Problem(线段树)

    Description

    Given a rooted tree, each node has a boolean (0 or 1) labeled on it. Initially, all the labels are 0.

    We define this kind of operation: given a subtree, negate all its labels.

    And we want to query the numbers of 1's of a subtree.

    Input

    Multiple test cases.

    First line, two integer N and M, denoting the numbers of nodes and numbers of operations and queries.(1<=N<=100000, 1<=M<=10000)

    Then a line with N-1 integers, denoting the parent of node 2..N. Root is node 1.

    Then M lines, each line are in the format "o node" or "q node", denoting we want to operate or query on the subtree with root of a certain node.

    Output

    For each query, output an integer in a line.

    Output a blank line after each test case.

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

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

      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 }
    View Code
  • 相关阅读:
    Kafka sender消息生产者
    springboot--websocket简单demo(一):session chat
    IDE引入mindmap插件,在项目中添加思维导图
    Redis启动命令
    Failure to find com.oracle:ojdbc6:jar:11.2.0.1.0
    Java秒杀系统实战系列~构建SpringBoot多模块项目
    利用java多线程技术往Elasticsearch导入千亿级数据
    list遍历陷阱分析原理
    Storm框架最显著的应用
    Apache Storm Trident
  • 原文地址:https://www.cnblogs.com/oyking/p/3224080.html
Copyright © 2011-2022 走看看