zoukankan      html  css  js  c++  java
  • CodeForces 383C-dfs序-线段树

    题意:一棵根为1的多叉树有n个点,题目有m次询问。第一行输入n和m,第二行输入n-1条边, 以后m行输入操作,操作有两种:1 x val 表示 节点的值x+val,同时它的儿子层节点的值-val,孙子层节点的值+val...如此往下直到叶子节点;2 x 表示输出x节点的当前值。

    思路:类似poj3321,用dfs序重新表示每个节点,这样更新子树的操作就变成更新区间了,区间是:[i, i+cnt]【当前节点的dfs序为 i, 儿子数为cnt】,查询同理,单点查询当前节点的dfs序。但是这道题的dfs序,奇、偶层的节点要分开来记录,也要建奇、偶两棵线段树。dfs过程中,还有每次更新查询都要判断在哪层。具体细节看代码。

    AC代码:

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <vector>
      4 #include <algorithm>
      5 #include <cstring>
      6 using namespace std;
      7 #define maxn 201000
      8 #define lson l, m, rt<<1
      9 #define rson m+1, r, rt<<1|1
     10 #define ll long long
     11 struct node
     12 {
     13     int cnt_o, cnt_e;  //分别记录奇层、偶层有几个儿子
     14     int val;
     15     int num, dep, next;   // num记录dfs序,dep 记录节点深度(这里节点1深度为1),next记录下一层的开头的节点。
     16 }arr[maxn];
     17 int sgt_o[maxn<<2], sgt_e[maxn<<2];
     18 int lazy_o[maxn<<2], lazy_e[maxn<<2];
     19 vector<int> odd, even;     //分别记录在奇、偶层的原节点序号
     20 int vis[maxn];
     21 int n, m;
     22 int next[maxn<<1], first[maxn], v[maxn<<1], u[maxn<<1];  //邻接表
     23 void init()
     24 {
     25     odd.clear(); even.clear();
     26     memset(first, -1, sizeof(first));
     27     memset(next, 0, sizeof(next));
     28     memset(vis, 0, sizeof(vis));
     29     for(int i = 1; i <= n; i++) {
     30         scanf("%d", &arr[i].val);
     31         arr[i].cnt_e = arr[i].cnt_o = arr[i].next = 0;
     32     }
     33     for(int i = 0; i < n-1; i++) {   //用邻接表存图
     34         scanf("%d%d", &u[i], &v[i]);
     35         next[i] = first[u[i]];
     36         first[u[i]] = i;
     37         u[n+i] = v[i];
     38         v[n+i] = u[i];
     39         next[n+i] = first[v[i]];
     40         first[v[i]] = n+i;
     41     }
     42 }
     43 struct child  //记录奇、偶的儿子数
     44 {
     45     int e, o;
     46 };
     47 child dfs(int i, int &num1, int &num2, int dep)  //num1是奇层的dfs序,num2是偶层的dfs序
     48 {
     49     if(dep&1) odd.push_back(i);
     50     else even.push_back(i);
     51     
     52     if(dep&1) arr[i].num = num1++;
     53     else arr[i].num = num2++;
     54     arr[i].dep = dep;
     55     
     56     vis[i] = 1;
     57     
     58     int flag = 0;
     59     if(dep&1)
     60         for(int e = first[i]; e != -1; e = next[e]) {
     61             if(!vis[v[e]]) {
     62                 if(!flag) {
     63                     arr[i].next = v[e]; flag = 1;
     64                 }
     65                 child x = dfs(v[e], num1, num2, dep+1);
     66                 arr[i].cnt_e += x.e;
     67                 arr[i].cnt_o += x.o;
     68             }
     69         }
     70     else {
     71         for(int e = first[i]; e != -1; e = next[e]) {
     72             if(!vis[v[e]]) {
     73                 if(!flag) {
     74                     arr[i].next = v[e]; flag = 1;
     75                 }
     76                 child x = dfs(v[e], num1, num2, dep+1);
     77                 arr[i].cnt_e += x.e;
     78                 arr[i].cnt_o += x.o;
     79             }
     80         }
     81     }
     82     child xx; xx.o = arr[i].cnt_o; xx.e = arr[i].cnt_e;
     83     if(dep&1) xx.o++; else xx.e++;
     84     return xx;
     85 }
     86 
     87 void build_o(int l, int r, int rt)   //建奇层节点的线段树
     88 {
     89     sgt_o[rt] = 0;
     90     if(l == r) {
     91         int x = odd[l-1];
     92         sgt_o[rt] = arr[x].val;
     93         return;
     94     }
     95     int m = (r+l)>>1;
     96     build_o(lson);
     97     build_o(rson);
     98 }
     99 void build_e(int l, int r, int rt)  //建偶层节点的线段树
    100 {
    101     sgt_e[rt] = 0;
    102     if(l == r) {
    103         int x = even[l-1];
    104         sgt_e[rt] = arr[x].val;
    105         return;
    106     }
    107     int m = (l+r)>>1;
    108     build_e(lson);
    109     build_e(rson);
    110 }
    111 void push_down(int rt, int x, int *lazy)
    112 {
    113     if(lazy[rt] != 0) {
    114         lazy[rt<<1] += lazy[rt];
    115         lazy[rt<<1|1] += lazy[rt];
    116         lazy[rt] = 0;
    117     }
    118 }
    119 void change(int l, int r, int rt, int L, int R, int del, int *sgt, int *lazy)
    120 {
    121     if(L <= l && r <= R)
    122     {
    123         lazy[rt] += del;
    124         return;
    125     }
    126     int x = (r-l+1);
    127     push_down(rt, x, lazy);
    128     int m = (l+r)>>1;
    129     if(L <= m) change(lson, L, R, del, sgt, lazy);
    130     if(m < R) change(rson, L, R, del, sgt, lazy);
    131 }
    132 int query(int l, int r, int rt, int pos, int *sgt, int *lazy)
    133 {
    134     if(l == r) {
    135         sgt[rt] += lazy[rt];
    136         lazy[rt] = 0;
    137         return sgt[rt];
    138     }
    139     int m = (l+r)>>1;
    140     push_down(rt, r-l+1, lazy);
    141     if(pos <= m) return query(lson, pos, sgt, lazy);
    142     return query(rson, pos, sgt, lazy);
    143 }
    144 void work()
    145 {
    146     init();
    147     int num1 = 1, num2 = 1;
    148     dfs(1, num1, num2, 1);
    149     int n1 = odd.size(), n2 = even.size(); 
    150     if(n1 > 0)build_o(1, n1, 1); 
    151     if(n2 > 0)build_e(1, n2, 1);
    152     while(m--) {
    153         int a, b; scanf("%d%d", &a, &b);
    154         if(a == 1) {
    155             int c; scanf("%d", &c);
    156             if(arr[b].dep&1) {
    157                 change(1, n1, 1, arr[b].num, arr[b].num+arr[b].cnt_o, c, sgt_o, lazy_o);
    158                 if(arr[b].next != 0) {
    159                     int ne = arr[b].next;
    160                     change(1, n2, 1, arr[ne].num, arr[ne].num+arr[b].cnt_e-1, -c, sgt_e, lazy_e);
    161                 }
    162             }
    163             else {
    164                 change(1, n2, 1, arr[b].num, arr[b].num+arr[b].cnt_e, c, sgt_e, lazy_e);
    165                 if(arr[b].next != 0) {
    166                     int ne = arr[b].next; 
    167                     change(1, n1, 1, arr[ne].num, arr[ne].num+arr[b].cnt_o-1, -c, sgt_o, lazy_o);
    168                 }
    169             }
    170         }
    171         else {
    172             int res;
    173             if(arr[b].dep&1) {
    174                 res = query(1, n1, 1, arr[b].num, sgt_o, lazy_o);
    175             }
    176             else {
    177                 res = query(1, n2, 1, arr[b].num, sgt_e, lazy_e);
    178             }
    179             printf("%d
    ", res);
    180         }
    181     }
    182 }
    183 int main()
    184 {
    185     while(scanf("%d%d", &n, &m) != EOF) work();
    186     return 0;
    187 }
    View Code
  • 相关阅读:
    java基础
    JAVASE 安装步骤
    MySQL 45道练习题
    MySQL 多表查询
    2018-08-07JDBC连接MySQL+增删改表格+SQL注入问题及其预处理对象PreparedStatement解决方案
    2018-08-06Java中的异常捕获和Throw详细细节
    2018-08-03List接口方法+LinkedList方法+Vector集合+Set接口下HashSet和LinkedHashSet集合+HashCode()+equals()方法对于Set接口判断重复的详细细节
    2018-08-01集合Collection+Iterator迭代器+泛型+增强For循环
    2018-07-31包装类与基本数据类型String的转换+System类详细知识+Arrays类+大数据(BigInteger+BigDecimal)运算
    2018-07-27Final+Static+匿名对象+3中代码块
  • 原文地址:https://www.cnblogs.com/ZiningTang/p/3968931.html
Copyright © 2011-2022 走看看