zoukankan      html  css  js  c++  java
  • bzoj 4034 [HAOI2015] T2(树链剖分,线段树)

    4034: [HAOI2015]T2

    Time Limit: 10 Sec  Memory Limit: 256 MB
    Submit: 1536  Solved: 508
    [Submit][Status][Discuss]

    Description

     有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个

    操作,分为三种:
    操作 1 :把某个节点 x 的点权增加 a 。
    操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
    操作 3 :询问某个节点 x 到根的路径中所有点的点权和。

    Input

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

    接下来一行 N 个整数,表示树中节点的初始权值。
    接下来 N-1 行每行三个正整数 fr, to , 表示该树中存在一条边 (fr, to) 。
    再接下来 M 行,每行分别表示一次操作。其中第一个数表示该操
    作的种类( 1-3 ) ,之后接这个操作的参数( x 或者 x a ) 。

    Output

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

    Sample Input

    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

    Sample Output

    6
    9
    13

    HINT

     对于 100% 的数据, N,M<=100000 ,且所有输入数据的绝对值都不


    会超过 10^6 。

    Source

    【思路】

      树链剖分,线段树

      线段树:区间和,区间修改add

    【代码】

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<vector>
      4 #include<iostream>
      5 #include<algorithm>
      6 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
      7 using namespace std;
      8 
      9 typedef long long LL;
     10 const int N = 400000+10;
     11 
     12 struct Node { LL sum,addv;
     13 }T[N<<1];
     14 
     15 int n,q,z,c[N];
     16 vector<int> g[N];
     17 //INIT
     18 int top[N],son[N],dep[N],fa[N],siz[N],w[N],mxw[N];
     19 void dfs1(int u) {
     20     son[u]=0; siz[u]=1;
     21     for(int i=0;i<g[u].size();i++) {
     22         int v=g[u][i];
     23         if(v!=fa[u]) {
     24             fa[v]=u , dep[v]=dep[u]+1;
     25             dfs1(v);
     26             siz[u]+=siz[v];
     27             if(siz[v]>siz[son[u]]) son[u]=v;
     28         }
     29     }
     30 }
     31 void dfs2(int u,int tp) {
     32     top[u]=tp; w[u]=mxw[u]=++z;
     33     if(son[u]) 
     34         dfs2(son[u],tp),mxw[u]=max(mxw[u],mxw[son[u]]);
     35     for(int i=0;i<g[u].size();i++) {
     36         int v=g[u][i];
     37         if(v!=fa[u] && v!=son[u])
     38             dfs2(v,v),mxw[u]=max(mxw[u],mxw[v]);
     39     }
     40 }
     41 //SEGMENT TREE
     42 void pushdown(int u,int l,int r) {
     43     if(T[u].addv && l<r) {
     44         int lc=u<<1,rc=lc|1,M=(l+r)>>1;
     45         T[lc].sum+=T[u].addv*(M-l+1);
     46         T[rc].sum+=T[u].addv*(r-M);
     47         T[lc].addv+=T[u].addv,T[rc].addv+=T[u].addv;
     48         T[u].addv=0;
     49     }
     50 }
     51 void update(int u,int L,int R,int l,int r,int x) {
     52     pushdown(u,L,R);
     53     if(l<=L && R<=r)
     54         T[u].addv+=x , T[u].sum+=x*(R-L+1);
     55     else {
     56         int M=(L+R)>>1,lc=u<<1,rc=lc|1;
     57         if(l<=M) update(lc,L,M,l,r,x);
     58         if(M<r) update(rc,M+1,R,l,r,x);
     59         T[u].sum=T[lc].sum+T[rc].sum;
     60     }
     61 }
     62 LL query(int u,int L,int R,int l,int r) {
     63     pushdown(u,L,R);
     64     if(l<=L && R<=r) return T[u].sum;
     65     else {
     66         int M=(L+R)>>1; LL ans=0;
     67         if(l<=M) ans+=query(u<<1,L,M,l,r);
     68         if(M<r) ans+=query(u<<1|1,M+1,R,l,r);
     69         return ans;
     70     }
     71 }
     72 //Ê÷Á´ÆÊ·Ö
     73 LL query(int u) {
     74     LL sum=0;
     75     while(top[u]!=1) {
     76         sum+=query(1,1,z,w[top[u]],w[u]);
     77         u=fa[top[u]];
     78     }
     79     sum+=query(1,1,z,1,w[u]);
     80     return sum;
     81 }
     82 
     83 void read(int& x) {
     84     char c=getchar(); int f=1; x=0;
     85     while(!isdigit(c)) {if(c=='-')f=-1;c=getchar();}
     86     while(isdigit(c)) x=x*10+c-'0',c=getchar();
     87     x*=f;
     88 }
     89 int main() {
     90     //freopen("in.in","r",stdin);
     91     //freopen("out.in","w",stdout);
     92     read(n),read(q);
     93     FOR(i,1,n) read(c[i]);
     94     int u,v,x,op,y;
     95     FOR(i,1,n-1) {
     96         read(u),read(v);
     97         g[u].push_back(v);
     98         g[v].push_back(u);
     99     }
    100     dfs1(1),dfs2(1,1);
    101     FOR(i,1,n) update(1,1,z,w[i],w[i],c[i]);
    102     while(q--) {
    103         read(op),read(x);
    104         if(op==1) 
    105             read(y),update(1,1,z,w[x],w[x],y);
    106         else if(op==2)
    107             read(y),update(1,1,z,w[x],mxw[x],y);
    108         else 
    109             printf("%lld
    ",query(x));
    110     }
    111     return 0;
    112 }
    View Code
  • 相关阅读:
    为什么要用webUI?
    探索WebKit内核(一)------ 菜鸟起步
    主进程退出的时候,杀死所有子进程
    那两年炼就的Android内功修养
    飞鸽---局域网聊天软件攻防战
    如何利用Fluxion诱惑目标用户获取WPA密码
    性能测试:CPU内存,硬盘IO读写,带宽速度,UnixBench
    解决maven编译错误:程序包com.sun.xml.internal.ws.spi不存在
    Apache-Flink深度解析-DataStream-Connectors之Kafka
    linux下find(文件查找)命令的用法总结
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5186522.html
Copyright © 2011-2022 走看看