zoukankan      html  css  js  c++  java
  • bzoj4034[HAOI2015]T2

    bzoj4034[HAOI2015]T2

    题意:

    N点树,以点 1 为根,且树点有边权。三种操作:把某个节点点权增加 a 、某个节点为根的子树中所有点的点权都增加 a 、询问某个节点到根的路径中所有点的点权和。

    题解:

    本题链剖可过。第二个操作只要每次在构造链的时候找到子树中在链中位置最大的节点,然后区间修改就行。听说正解是DFS序,不过我不会。

    代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #define inc(i,j,k) for(int i=j;i<=k;i++)
     5 #define maxn 200000
     6 #define ll long long
     7 using namespace std;
     8 
     9 struct e{int t,n;}; e es[maxn]; int ess,g[maxn];
    10 void pe(int f,int t){es[++ess]=(e){t,g[f]}; g[f]=ess; es[++ess]=(e){f,g[t]}; g[t]=ess;}
    11 int l[maxn*4],r[maxn*4],ch[maxn*4][2],fa[maxn],dep[maxn],pos[maxn],top[maxn],sz[maxn],sgs,mx[maxn];
    12 ll v[maxn][2],sm[maxn*4],tg[maxn*4];
    13 void dfs(int x){
    14     sz[x]=1; for(int i=g[x];i;i=es[i].n)if(es[i].t!=fa[x]){
    15         fa[es[i].t]=x; dep[es[i].t]=dep[x]+1; dfs(es[i].t); sz[x]+=sz[es[i].t];
    16     }
    17 }
    18 void buildchain(int x,int ps){
    19     pos[x]=mx[x]=++sgs; v[sgs][1]=v[x][0]; top[x]=ps; int mx1=0,mx2=0;
    20     for(int i=g[x];i;i=es[i].n)if(es[i].t!=fa[x]&&mx2<sz[es[i].t])mx2=sz[es[i].t],mx1=es[i].t;
    21     if(mx1)buildchain(mx1,ps),mx[x]=max(mx[x],mx[mx1]);
    22     for(int i=g[x];i;i=es[i].n)if(es[i].t!=fa[x]&&es[i].t!=mx1)
    23         buildchain(es[i].t,es[i].t),mx[x]=max(mx[x],mx[es[i].t]);
    24 }
    25 void pushdown(int x){
    26     if(x&&tg[x]){
    27         int lc=ch[x][0],rc=ch[x][1];
    28         if(lc)sm[lc]+=(r[lc]-l[lc]+1)*tg[x],tg[lc]+=tg[x];
    29         if(rc)sm[rc]+=(r[rc]-l[rc]+1)*tg[x],tg[rc]+=tg[x];
    30         tg[x]=0;
    31     }
    32 }
    33 void build(int x,int L,int R){
    34     if(L==R)sm[x]=v[L][1],ch[x][0]=ch[x][1]=0,l[x]=r[x]=L;else{
    35         ch[x][0]=x<<1,l[x]=L,ch[x][1]=x<<1|1,r[x]=R; int M=(L+R)>>1;
    36         build(ch[x][0],L,M); build(ch[x][1],M+1,R); sm[x]=sm[ch[x][0]]+sm[ch[x][1]];
    37     }
    38 }
    39 ll query(int x,int L,int R){
    40     pushdown(x);
    41     if(L<=l[x]&&r[x]<=R)return sm[x];else{
    42         ll q=0;int M=(l[x]+r[x])>>1; if(L<=M)q+=query(ch[x][0],L,R); if(M<R)q+=query(ch[x][1],L,R);
    43         return q;
    44     }
    45 }
    46 void add(int x,int L,int R,ll val){
    47     pushdown(x);
    48     if(L<=l[x]&&r[x]<=R)tg[x]+=val,sm[x]+=(r[x]-l[x]+1)*val;else{
    49         int M=(l[x]+r[x])>>1; if(L<=M)add(ch[x][0],L,R,val); if(M<R)add(ch[x][1],L,R,val);
    50         sm[x]=sm[ch[x][0]]+sm[ch[x][1]];
    51     }
    52 }
    53 inline ll querysum(int x){ll q=0; while(x)q+=query(1,pos[top[x]],pos[x]),x=fa[top[x]]; return q;}
    54 void init1(){ess=0; memset(g,0,sizeof(g));}
    55 void init2(){dep[1]=fa[1]=0; dfs(1); sgs=0; buildchain(1,1); build(1,1,sgs);}
    56 int n,m;
    57 int main(){
    58     //freopen("test.txt","r",stdin);
    59     scanf("%d%d",&n,&m); inc(i,1,n)scanf("%lld",&v[i][0]); init1();
    60     inc(i,1,n-1){int a,b; scanf("%d%d",&a,&b); pe(a,b);} init2();
    61     inc(i,1,m){
    62         int opt,x;ll y; scanf("%d%d",&opt,&x);
    63         if(opt==1)scanf("%lld",&y),add(1,pos[x],pos[x],y);
    64         if(opt==2)scanf("%lld",&y),add(1,pos[x],mx[x],y);
    65         if(opt==3)printf("%lld
    ",querysum(x));
    66     }
    67     return 0;
    68 }

    20160425

  • 相关阅读:
    多表联合查询,利用 concat 模糊搜索
    order by 中利用 case when 排序
    Quartz.NET 3.0.7 + MySql 动态调度作业+动态切换版本+多作业引用同一程序集不同版本+持久化+集群(一)
    ASP.NET Core 2.2 基础知识(十八) 托管和部署 概述
    ASP.NET Core 2.2 基础知识(十七) SignalR 一个极其简陋的聊天室
    ASP.NET Core 2.2 基础知识(十六) SignalR 概述
    ASP.NET Core 2.2 基础知识(十五) Swagger
    ASP.NET Core 2.2 基础知识(十四) WebAPI Action返回类型(未完待续)
    linux磁盘管理 磁盘查看操作
    linux磁盘管理 文件挂载
  • 原文地址:https://www.cnblogs.com/YuanZiming/p/5689579.html
Copyright © 2011-2022 走看看