zoukankan      html  css  js  c++  java
  • HDU 3966 Aragorn's Story

    题意:
    给一棵树,并给定各个点权的值,然后有3种操作:
    I C1 C2 K: 把C1与C2的路径上的所有点权值加上K
    D C1 C2 K:把C1与C2的路径上的所有点权值减去K
    Q C:查询节点编号为C的权值
    思路:
    先树链剖分,然后用线段树维护一下

    模板题,具体细节看代码

      1 const int maxn = 50000 + 10;
      2 const int maxnode = maxn * 4;
      3 
      4 int n, m, p;
      5 //线段树部分
      6 int add_value, qL, qR;
      7 int addv[maxnode];
      8 void update(int o, int L, int R) 
      9 {
     10     if (qL <= L && R <= qR) 
     11     {
     12         addv[o] += add_value;
     13     }
     14     else 
     15     {
     16         int M = L + (R - L) / 2;
     17         if (qL <= M) update(lson);
     18         if (qR > M) update(rson);
     19     }
     20 }
     21 
     22 void query(int o, int L, int R, LL add) {
     23     if (qL <= L && R <= qR) {
     24         printf("%d
    ", add + addv[o]);
     25         return;
     26     }
     27     int M = L + (R - L) / 2;
     28     if (qL <= M) query(lson, add + addv[o]);
     29     if (qR > M) query(rson, add + addv[o]);
     30 }
     31 
     32 //树链剖分部分:
     33 //
     34 //u为连接的点,w为边权
     35 struct Edge { int v, w; };
     36 vector<Edge> G[maxn];
     37 
     38 //往往是双向边
     39 void add_edge(int u, int v, int w)
     40 {
     41     G[u].push_back((Edge){v,w});
     42     G[v].push_back((Edge){u,w});
     43 }
     44 
     45 struct Node
     46 {
     47     int size, dep, son, top, fa, ti;
     48     //依次表示第i个节点的:
     49     //子节点数量,深度,所在链的顶端,重儿子,dfs序
     50 } t[maxn];
     51 
     52 int dfs_clock;//DFS时间序列
     53 
     54 void dfs1(int u, int pa, int depth)//第一次DFS,得到size,dep,fa以及son的数据
     55 {
     56     t[u].son = 0; //重儿子,为0表示没有重儿子
     57     t[u].size = 1;    //节点数量
     58     t[u].dep = depth;
     59     t[u].fa = pa;
     60     for (int i = 0; i != G[u].size(); ++ i)
     61     {
     62         int v = G[u][i].v;
     63         if (v == pa) continue;
     64         dfs1(v, u, depth + 1);
     65         t[u].size += t[v].size;
     66         if (t[v].size > t[t[u].son].size) t[u].son = v;
     67     }
     68 }
     69 
     70 void dfs2(int u, int pa)    // 得到时间戳等数据,u为当前节点,pa为父链顶端节点
     71 {
     72     t[u].ti = ++ dfs_clock; //u这个节点的时间戳是dfs_clock,dfs_clock下标是从1开始的,没有0!
     73     t[u].top = pa;        //top是u所在链的顶端
     74     if (t[u].son != 0) dfs2(t[u].son, t[u].top);    //如果节点有重儿子,那么依旧是以pa为链顶端的一条链
     75     for (int i = 0; i != G[u].size(); ++ i)
     76     {
     77         int v = G[u][i].v;
     78         if (v == t[u].son || v == t[u].fa)    continue;//重儿子或者父节点,则跳过
     79         dfs2(v, v);//新的一条链
     80     }
     81 }
     82 
     83 void lca(int x, int y)//更新x到y的之间所有的区间
     84 {
     85     while (t[x].top != t[y].top)
     86     {
     87         if (t[t[x].top].dep < t[t[y].top].dep) swap(x,y); //x深 y浅
     88         qL=t[t[x].top].ti;
     89         qR=t[x].ti;
     90         update(1,1,n);
     91         x = t[t[x].top].fa;
     92     }
     93     if (t[x].dep > t[y].dep) swap(x, y);//x是上面一些的节点
     94     qL=t[x].ti;
     95     qR=t[y].ti;
     96     update(1,1,n);
     97 }
     98 
     99 int value[maxn];
    100 void init()
    101 {
    102     dfs_clock = 0;
    103     memset(addv, 0, sizeof(addv));
    104     for (int i = 1; i <= n; i++)
    105     {
    106         scanf("%d", value + i);
    107         G[i].clear();
    108     }
    109     int u, v;
    110     for (int i = 1; i <= m; i++)
    111     {
    112         scanf("%d%d", &u, &v);
    113         add_edge(u, v, 0);
    114     }
    115 }
    116 
    117 void solve()
    118 {
    119     dfs1(1, 0, 1);
    120     dfs2(1, 0);
    121 
    122     for (int i = 1; i <= n; i++)
    123     {
    124         add_value = value[i];
    125         qL = qR = t[i].ti;
    126         update(1, 1, n);
    127     }
    128     char op[5];
    129     int u, v, w;
    130     while (p--)
    131     {
    132         scanf("%s", op);
    133         if (op[0] == 'Q')
    134         {
    135             scanf("%d", &u);
    136             qL = qR = t[u].ti;
    137             query(1, 1, n, 0);
    138             continue;
    139         }
    140         scanf("%d%d%d", &u, &v, &w);
    141         if (op[0] == 'D') w = -w;
    142         add_value = w;
    143         lca(u, v);
    144     }
    145 }
    146 
    147 int main()
    148 {
    149     while (scanf("%d%d%d", &n, &m, &p) == 3)
    150     {
    151         init();
    152         solve();
    153     }
    154     return 0;
    155 }
  • 相关阅读:
    POJ 1328 Radar Installation
    POJ 1700 Crossing River
    POJ 1700 Crossing River
    poj 3253 Fence Repair (贪心,优先队列)
    poj 3253 Fence Repair (贪心,优先队列)
    poj 3069 Saruman's Army(贪心)
    poj 3069 Saruman's Army(贪心)
    Redis 笔记与总结2 String 类型和 Hash 类型
    数据分析方法有哪些_数据分析方法
    数据分析方法有哪些_数据分析方法
  • 原文地址:https://www.cnblogs.com/liangyongrui/p/6029542.html
Copyright © 2011-2022 走看看