JZYZOJ1539[haoi2015]T2 树链剖分

http://172.20.6.3/Problem_Show.asp?id=1539

在学校的OJ又写了一次,RE了好多次,原来haoi的时候这道题需要开栈+快读,裸数据结构30分,加上快读50分。
oi考试的时候原来不能汇编开栈,只能写手工栈orz,学长说当时省选最高分50,本来以为很简单的题没想到这么套路。

代码

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<cmath>
  6 using namespace std;
  7 #define lc x*2
  8 #define rc x*2+1
  9 const int maxn=100010;
 10 int n,m;
 11 long long a[maxn]={};
 12 struct nod{
 13     int y,next;
 14 }e[maxn*2];
 15 int head[maxn]={},tot=0;
 16 long long fa[maxn]={},dep[maxn]={},siz[maxn]={};
 17 long long kid[maxn]={},top[maxn]={},val[maxn]={};
 18 struct seg{
 19     long long l,r,v,w,siz;
 20     seg(){l=r=v=w=siz=0;}
 21 }t[maxn*4];
 22 void init(long long x,long long y){
 23     e[++tot].y=y;e[tot].next=head[x];head[x]=tot;
 24 }
 25 int build1(int x,int pa){
 26     int y,hug=0,si,tsn=1;fa[x]=pa;
 27     for(int i=head[x];i;i=e[i].next){
 28         y=e[i].y;
 29         if(y==pa)continue;
 30         si=build1(y,x);tsn+=si;
 31         if(si>hug)hug=si,kid[x]=y;
 32     }return siz[x]=tsn;
 33 }
 34 void build2(int x,int pa){
 35     int y;dep[x]=++tot;top[x]=pa;
 36     val[dep[x]]=a[x];
 37     if(kid[x])build2(kid[x],pa);
 38     for(int i=head[x];i;i=e[i].next){
 39         y=e[i].y;
 40         if(y==kid[x]||y==fa[x])continue;
 41         build2(y,y);
 42     }
 43 }
 44 void pushup(int x){
 45     if(t[x].siz>1)t[x].v=t[lc].v+t[rc].v;
 46     t[x].v+=t[x].w*t[x].siz;
 47 }
 48 void build(int x,int l,int r){
 49     t[x].r=r;t[x].l=l;t[x].siz=r-l+1;
 50     if(l==r){t[x].v=val[l];return;}
 51     int mid=(l+r)/2;
 52     build(lc,l,mid);
 53     build(rc,mid+1,r);
 54     pushup(x);
 55 }
 56 void add(int x,int l,int r,long long w){
 57     if(l<=t[x].l&&t[x].r<=r){
 58         if(t[x].l==t[x].r)t[x].v+=w;
 59         else t[x].w+=w;pushup(x);
 60         return;
 61     }
 62     int mid=(t[x].l+t[x].r)/2;
 63     if(l<=mid)add(lc,l,r,w);
 64     if(r>mid)add(rc,l,r,w);
 65     pushup(x);
 66 }
 67 long long sum(int x,int l,int r,long long w){
 68     if(l<=t[x].l&&t[x].r<=r){
 69         return t[x].v+t[x].siz*w;
 70     }
 71     int mid=(t[x].l+t[x].r)/2;long long ans=0;
 72     if(l<=mid)ans+=sum(lc,l,r,w+t[x].w);
 73     if(r>mid)ans+=sum(rc,l,r,w+t[x].w);
 74     return ans;
 75 }
 76 long long doit(int x){
 77     int a=top[x];long long ans=0;
 78     while(a!=1){
 79         ans+=sum(1,dep[a],dep[x],0);
 80         x=fa[a];a=top[x];
 81     }
 82     ans+=sum(1,dep[a],dep[x],0);
 83     return ans;
 84 }
 85 long long read(){
 86     char ch=getchar();long long x=0,f=1;
 87     while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
 88     while(ch>=‘0‘&&ch<=‘9‘){x*=10;x+=ch-‘0‘;ch=getchar();}
 89     return x*f;
 90 }
 91 int main(){
 92     //freopen("wtf.in","r",stdin);
 93     int size = 256 << 20; // 256MB
 94     char *p = (char*)malloc(size) + size;
 95     __asm__("movl %0, %%esp\n" :: "r"(p));
 96     n=read();m=read();int x,y,v;
 97     for(int i=1;i<=n;i++)a[i]=read();
 98     for(int i=1;i<n;i++){x=read();y=read();init(x,y);init(y,x);}
 99     tot=0;build1(1,1);build2(1,1);
100     build(1,1,n);
101     for(int i=1;i<=m;i++){
102         scanf("%d",&v);
103         if(v==1){
104             scanf("%d%d",&x,&y);
105             add(1,dep[x],dep[x],y);
106         }
107         else if(v==2){
108             scanf("%d%d",&x,&y);
109             add(1,dep[x],dep[x]+siz[x]-1,y);
110         }
111         else{
112             scanf("%d",&x);
113             printf("%I64d\n",doit(x));
114         }
115     }
116     return 0;
117 }

时间: 2024-07-31 14:32:26

JZYZOJ1539[haoi2015]T2 树链剖分的相关文章

BZOJ 4034: [HAOI2015]T2 树链剖分

4034: [HAOI2015]T2 Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a . 操作 3 :询问某个节点 x 到根的路径中所有点的点权和. Input 第一行包含两个整数 N, M .表示点数和操作数. 接下来一行 N 个整数,表示树中节点的初始权值. 接下来 N-1 行每行三个正整数 fr, to , 表示该树

BZOJ 4034 [HAOI2015]T2 树链剖分+线段树

题意: 一棵以1为根的树,有n个节点,m个操作. 第一种单点修改. 第二种修改一个点的子树. 第三种询问一个点到根的路径上所有点的权值和. 解析: 看到有人在做我就跑过来看了一下,看完题发现这不SB题么- - 于是就写了下,差点被出题人气死. TMD 那个 fr , to 难道就是逗我玩的? 你丫fr,to不代表有向边? 这么出题不会掉RP? 改了20分钟就这错了?你逗我? 第一种操作略 第二种操作修改子树-dfs序. 第三种链剖完之后直接找就行了. 复杂度O(nlog^2n); 代码: #in

【十一联考 1】T2 树链剖分

算法思路就不说了,其实比较简单 这里讲一下坑点: 1.虽然我们可以将边权压到点上,但是当根不同时,差分数组显然不同.所以我们不能真的将边权看做点权,换根时还是要将其当做边权来考虑. 1.更新时,我们设dp[u]表示u节点为根时的最大价值,由于经过点u后,点v的儿子将变成点u,所以此时我们要更新点v的儿子中的最大值以及次大值.注意!不止要更新最大值,次大值也要正确维护 我的代码没有加优化,因为保证正确就不错了 #include<bits/stdc++.h> using namespace std

bzoj 4034: [HAOI2015]树上操作 树链剖分+线段树

4034: [HAOI2015]树上操作 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 4352  Solved: 1387[Submit][Status][Discuss] Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a . 操作 3 :询问某个节点 x 到根的路径中所有

[HAOI2015]树上操作(树链剖分)

[HAOI2015]树上操作(luogu) Description 题目描述 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a . 操作 3 :询问某个节点 x 到根的路径中所有点的点权和. 输入格式 第一行包含两个整数 N, M .表示点数和操作数.接下来一行 N 个整数,表示树中节点的初始权值.接下来 N-1 行每行两个正整数 from, to

【bzoj4034】【HAOI2015】【树上操作】【树链剖分】

Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a . 操作 3 :询问某个节点 x 到根的路径中所有点的点权和. Input 第一行包含两个整数 N, M .表示点数和操作数. 接下来一行 N 个整数,表示树中节点的初始权值. 接下来 N-1 行每行三个正整数 fr, to , 表示该树中存在一条边 (fr, to) . 再

bzoj4304 (树链剖分+线段树)

Problem T2 (bzoj4304 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a . 操作 3 :询问某个节点 x 到根的路径中所有点的点权和. 解题分析 练手题.树链剖分+线段树. 参考程序 1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #incl

【BZOJ1036】树的统计Count(树链剖分)

题意:一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 I II. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身 1<=n<=30000,0<=q<=200000:中途操作中保证每个节点的权值w在-30000到30000之间. 思路:树链

hdu 5893 (树链剖分+合并)

List wants to travel Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 429    Accepted Submission(s): 92 Problem Description A boy named List who is perfect in English. Now he wants to travel an