• 树链剖分-模板题 HAOI2015


      1 #include <stdio.h>
      2 #include <vector>
      3 
      4 using namespace std;
      5 
      6 typedef long long LL;
      7 
      8 const int _N = 1000000;
      9 
     10 vector<LL> G[_N];
     11 LL Size[_N], ID[_N], Anc[_N], Hson[_N], D[_N], Dad[_N], A[_N];
     12 LL Seg_root, Seg_cnt, L[_N], R[_N], Sum[_N], Lazy[_N];//segt
     13 LL N, ID_cnt;
     14 
     15 void Find(LL node, LL dad, LL deep)
     16 {
     17     LL mx = -1;
     18     Size[node] = 1, D[node] = deep, Dad[node] = dad;
     19     for (LL i = 0; i != G[node].size(); ++i) {
     20         LL v = G[node][i];
     21         if (v == dad) continue;
     22         Find(v, node, deep + 1), Size[node] += Size[v];
     23         if (mx == -1 || Size[G[node][mx]] < Size[v]) mx = i;
     24     }
     25     if (mx != -1) Hson[node] = G[node][mx];
     26     return;
     27 }
     28 
     29 void Connect(LL node, LL anc)
     30 {
     31     ID[node] = ++ID_cnt, Anc[node] = anc;
     32     if (Hson[node]) Connect(Hson[node], anc);
     33     for (LL i = 0; i != G[node].size(); ++i) {
     34         LL v = G[node][i];
     35         if (v == Dad[node] || v == Hson[node]) continue;
     36         Connect(v, v);
     37     }
     38     return;
     39 }
     40 
     41 void Seg_PD(LL &p, LL l, LL r)
     42 {
     43     if (l == r) { Lazy[p] = 0; return; }
     44     
     45     if (!L[p]) L[p] = ++Seg_cnt;
     46     if (!R[p]) R[p] = ++Seg_cnt;
     47     LL mid = l+r >> 1;
     48     Sum[L[p]] += Lazy[p] * (mid-l+1), Lazy[L[p]] += Lazy[p];
     49     Sum[R[p]] += Lazy[p] * (r-mid), Lazy[R[p]] += Lazy[p];
     50     Lazy[p] = 0;
     51     return;
     52 }
     53 
     54 void Seg_Add(LL &p, LL l, LL r, LL s, LL t, LL d)
     55 {
     56     if (!p) p = ++Seg_cnt;
     57     if (s <= l && r <= t) { Sum[p] += d * (r-l+1), Lazy[p] += d; return; }
     58     LL mid = l+r >> 1;
     59     if (Lazy[p]) Seg_PD(p, l, r);
     60     if (s <= r && t > mid) Seg_Add(R[p], mid+1, r, s, t, d);
     61     if (s <= mid && t >= l) Seg_Add(L[p], l, mid, s, t, d);
     62     Sum[p] = Sum[R[p]] + Sum[L[p]];
     63     return;
     64 }
     65 
     66 LL Seg_Qry(LL &p, LL l, LL r, LL s, LL t)
     67 {
     68     if (!p) p = ++Seg_cnt;
     69     if (s <= l && r <= t) return Sum[p];
     70     LL mid = l+r >> 1, sum = 0;
     71     if (Lazy[p]) Seg_PD(p, l, r);
     72     if (s <= r && t > mid) sum += Seg_Qry(R[p], mid+1, r, s, t);
     73     if (s <= mid && t >= l) sum += Seg_Qry(L[p], l, mid, s, t);
     74     return sum;
     75 }
     76 
     77 void Add_s(LL k, LL d)
     78 {
     79     Seg_Add(Seg_root, 1, N, ID[k], ID[k], d);
     80     return;
     81 }
     82 
     83 void Add_r(LL k, LL d)
     84 {
     85     Seg_Add(Seg_root, 1, N, ID[k], ID[k] + Size[k] - 1, d);
     86     return;
     87 }
     88 
     89 LL Qry(LL x, LL y)
     90 {
     91     LL sum = 0;
     92     while (Anc[x] != Anc[y]) {
     93         if (D[Anc[x]] < D[Anc[y]]) swap(x, y);
     94         sum += Seg_Qry(Seg_root, 1, N, ID[Anc[x]], ID[x]);
     95         x = Dad[Anc[x]];
     96     }
     97     if (D[x] > D[y]) swap(x, y);
     98     sum += Seg_Qry(Seg_root, 1, N, ID[x], ID[y]);
     99     return sum;
    100 }
    101 
    102 int main_main()
    103 {
    104     LL M, i;
    105     scanf("%lld%lld", &N, &M);
    106     for (i = 1; i <= N; ++i) scanf("%lld", &A[i]);
    107     for (i = 1; i < N; ++i) {
    108         LL t1, t2;
    109         scanf("%lld%lld", &t1, &t2);
    110         G[t1].push_back(t2), G[t2].push_back(t1);
    111     }
    112     
    113     Find(1, -1218, 1);
    114     Connect(1, 1);
    115     for (i = 1; i <= N; ++i) Add_s(i, A[i]);
    116 
    117     for (i = 1; i <= M; ++i) {
    118         LL ins, t1, t2;
    119         scanf("%lld%lld", &ins, &t1);
    120         if (ins == 1) {//add_s
    121             scanf("%lld", &t2);
    122             Add_s(t1, t2);
    123         } else if (ins == 2) {//add_r
    124             scanf("%lld", &t2);
    125             Add_r(t1, t2);
    126         } else if (ins == 3) {//qry
    127             printf("%lld
    ", Qry(1, t1));
    128         }
    129     }
    130     return 0;
    131 }
    132 
    133 const int main_stack=16;    
    134 char my_stack[128<<20];    
    135 int main() {    
    136   __asm__("movl %%esp, (%%eax);
    "::"a"(my_stack):"memory");    
    137   __asm__("movl %%eax, %%esp;
    "::"a"(my_stack+sizeof(my_stack)-main_stack):"%esp");    
    138   main_main();    
    139   __asm__("movl (%%eax), %%esp;
    "::"a"(my_stack):"%esp");    
    140   return 0; //add stack copy copy!!!   
    141 } 

    敲了一个树剖模板,顺便复习了一下动态开点的线段树.

    NKOJ需要扩栈!

    题目

    【HAOI2015】树上操作
    时间限制 : - MS   空间限制 : 265536 KB 
    评测说明 : 1s
    问题描述

     有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个操作,分为三种:

    操作 1 :把某个节点 x 的点权增加 a 。

    操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。

    操作 3 :询问某个节点 x 到根的路径中所有点的点权和。

    输入格式

     第一行包含两个整数 N, M 。表示点数和操作数。

    接下来一行 N 个整数,表示树中节点的初始权值。

    接下来 N-1 行每行三个正整数 fr, to , 表示该树中存在一条边 (fr, to) 。

    再接下来 M 行,每行分别表示一次操作。其中第一个数表示该操

    作的种类( 1-3 ) ,之后接这个操作的参数( x 或者 x a ) 。

    输出格式

    对于每个询问操作,输出该询问的答案。答案之间用换行隔开。

    样例输入

    5 5
    1 2 3 4 5
    1 2
    1 4
    2 3
    2 5
    3 3
    1 2 1
    3 5
    2 1 2
    3 3

    样例输出

    6
    9
    13

    提示

    对于 100% 的数据, N,M<=100000 ,且所有输入数据的绝对值都不会超过 10^6 。

  • 相关阅读:
    jenkins代码自动部署
    jenkins安装
    git图形管理工具
    gitlab自动备份恢复与卸载
    linux下获取外网IP
    网站安全webshell扫描
    jQuery动画效果实现
    form表单中的enctype属性什么意思?
    你那么努力又怎么样!
    话语
  • 原文地址:https://www.cnblogs.com/ghcred/p/8877031.html
Copyright © 2020-2023  润新知