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 }
  • 相关阅读:
    每一次面试都是提升(一)
    Gof设计模式分组
    MSSqlServer 通过sql语句 还原数据库(已有备份文件)
    自定义配置节与配置节的读取
    Javascript判断时间大小的方法
    C#微信开发之旅(十三):V2订单查询&退款(完结)
    C#微信开发之旅(十二):V2告警接口&维权接口
    C#微信开发之旅(十一):V2发货接口
    C#微信开发之旅(十):APP预支付及支付参数生成(V2)
    C#微信开发之旅(九):JSAPI支付(V3)
  • 原文地址:https://www.cnblogs.com/liangyongrui/p/6029542.html
Copyright © 2011-2022 走看看