HDU3966 Aragorn's Story 树链剖分+线段树

区间更新,单点查询,,,,奇葩,HDU上强行加了扩栈才过。

  1 #pragma comment(linker, "/STACK:1024000000,1024000000")
  2
  3 #include <cstdio>
  4 #include <cstring>
  5 #include <algorithm>
  6 using namespace std;
  7 #define lson l,m,rt<<1
  8 #define rson m+1,r,rt<<1|1
  9 const int maxn = 50005;
 10 struct edge
 11 {
 12     int v,next;
 13 }e[maxn*2];
 14 int head[maxn],cnt,sum[maxn<<2],lazy[maxn<<2],val[maxn];
 15 int siz[maxn],son[maxn],fa[maxn],top[maxn],tid[maxn],dep[maxn],lable;
 16 int n,m,p;
 17 void init()
 18 {
 19     memset(head,-1,sizeof(head));
 20     memset(lazy,0,sizeof(lazy));
 21     memset(sum,0,sizeof(sum));
 22     cnt = lable = 0;
 23 }
 24 void add(int u,int v)
 25 {
 26     e[cnt].v = v;
 27     e[cnt].next = head[u];
 28     head[u] = cnt++;
 29 }
 30 void find_heavy(int rt,int father,int depth)
 31 {
 32     fa[rt] = father;
 33     siz[rt] = 1;
 34     son[rt] = 0;
 35     dep[rt] = depth;
 36     int maxsize = 0;
 37     for(int i = head[rt];i!=-1;i = e[i].next)if(e[i].v!=father)
 38     {
 39         find_heavy(e[i].v,rt,depth+1);
 40         siz[rt]+=siz[e[i].v];
 41         if(siz[rt]>maxsize)
 42             maxsize = siz[rt],son[rt] = e[i].v;
 43     }
 44 }
 45 void connect(int rt,int anc)
 46 {
 47     tid[rt] = ++lable;
 48     top[rt] = anc;
 49     if(son[rt])connect(son[rt],anc);
 50     for(int i = head[rt];i!=-1;i = e[i].next)
 51         if(e[i].v!=fa[rt]&&e[i].v!=son[rt])
 52             connect(e[i].v,e[i].v);
 53 }
 54 void pushup(int rt)
 55 {
 56     sum[rt] = sum[rt<<1]+sum[rt<<1|1];
 57 }
 58 void pushdown(int rt,int m)
 59 {
 60     if(lazy[rt])
 61     {
 62         lazy[rt<<1]+=lazy[rt];
 63         lazy[rt<<1|1]+=lazy[rt];
 64         sum[rt<<1]+=lazy[rt]*(m-(m>>1));
 65         sum[rt<<1|1]+=lazy[rt]*(m>>1);
 66         lazy[rt] = 0;
 67     }
 68 }
 69 void update(int L,int R,int v,int l,int r,int rt)
 70 {
 71     if(L<=l&&r<=R){
 72         lazy[rt]+=v;
 73         sum[rt]+=v*(r-l+1);
 74         return;
 75     }
 76     pushdown(rt,r-l+1);
 77     int m = (l+r)>>1;
 78     if(L<=m)update(L,R,v,lson);
 79     if(m<R)update(L,R,v,rson);
 80     pushup(rt);
 81 }
 82 void change(int x,int y,int c)
 83 {
 84     while(top[x]!=top[y])
 85     {
 86         if(dep[top[x]]<dep[top[y]])swap(x,y);
 87         update(tid[top[x]],tid[x],c,1,n,1);
 88         x = fa[top[x]];
 89     }
 90     if(dep[x]>dep[y])swap(x,y);
 91     update(tid[x],tid[y],c,1,n,1);
 92 }
 93 int query(int L,int R,int l,int r,int rt)
 94 {
 95     if(L<=l&&r<=R)return sum[rt];
 96     pushdown(rt,r-l+1);
 97     int m = (l+r)>>1,ret = 0;
 98     if(L<=m)ret+=query(L,R,lson);
 99     if(m<R)ret+=query(L,R,rson);
100     return ret;
101 }
102 int main()
103 {
104     //freopen("in.txt","r",stdin);
105     while(~scanf("%d%d%d",&n,&m,&p))
106     {
107         for(int i = 1;i<=n;++i)scanf("%d",&val[i]);
108         init();
109         for(int i = 1;i<=m;++i)
110         {
111             int u,v;
112             scanf("%d%d",&u,&v);
113             add(u,v);add(v,u);
114         }
115         find_heavy(1,1,1);
116         connect(1,1);
117         for(int i = 1;i<=n;++i)update(tid[i],tid[i],val[i],1,n,1);
118         while(p--)
119         {
120             char s[2];int a,b,c;
121             scanf("%s",s);
122             if(s[0]==‘I‘){
123                 scanf("%d%d%d",&a,&b,&c);
124                 change(a,b,c);
125             }
126             else if(s[0]==‘D‘){
127                 scanf("%d%d%d",&a,&b,&c);
128                 change(a,b,-c);
129             }
130             else{
131                 scanf("%d",&a);
132                 printf("%d\n",query(tid[a],tid[a],1,n,1));
133             }
134         }
135     }
136     return 0;
137 }

HDU3966 Aragorn's Story 树链剖分+线段树

时间: 2024-10-26 18:39:55

HDU3966 Aragorn's Story 树链剖分+线段树的相关文章

HDU-3966 Aragorn&#39;s Story(树链剖分+线段树)

Aragorn's Story Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 12479    Accepted Submission(s): 3331 Problem Description Our protagonist is the handsome human prince Aragorn comes from The Lor

Hdu 3966 Aragorn&#39;s Story (树链剖分 + 线段树区间更新)

题目链接: Hdu 3966 Aragorn's Story 题目描述: 给出一个树,每个节点都有一个权值,有三种操作: 1:( I, i, j, x ) 从i到j的路径上经过的节点全部都加上x: 2:( D, i, j, x ) 从i到j的路径上经过的节点全部都减去x: 3:(Q, x) 查询节点x的权值为多少? 解题思路: 可以用树链剖分对节点进行hash,然后用线段树维护(修改,查询),数据范围比较大,要对线段树进行区间更新 1 #include <cstdio> 2 #include

HDU 3966 Aragorn&#39;s Story (树链剖分+线段树)

题意:给你一棵树,然后有三种操作 I L R K: 把L与R的路径上的所有点权值加上K D L R K:把L与R的路径上的所有点权值减去K Q X:查询节点编号为X的权值 思路:树链剖分裸题(我还没有怎么学懂,但基本已经没有什么太大的问题,主要的问题就在于点或者边对于数据结构的映射关系是,主要没有单独手写过树链剖分,所以对这部分 没有什么体会) 我们知道树链剖分是一种将树剖为链的一种算法,其思想和dfs序差不多,但根据树链剖分的性质,我们的重链是连续的区间,这样对于重链或者重链上的点我们可以方便

hdu3966 树链剖分+线段树 裸题

HDU - 3966 题意:给一颗树,3种操作,Q u 查询u节点的权值,I a b c 对a到b的路径上每个点的点权增加c,D a b c 对a b 路径上所有点的点权减少c 思路:树链剖分+线段树,2个问题,第一,如果是先建树再输入点的点权,记录tip(点映射到线段树后的位置),如果先输入点权,再建树,不仅要记录tip还要记录ran(线段树上某个位置上的点对应的树上点的序号,与tip是相互映射):第二,连接起线段树和树链剖分的是get函数,区间操作才需要用到get函数,单点操作直接在线段树上

Aizu 2450 Do use segment tree 树链剖分+线段树

Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show.php?pid=39566 Description Given a tree with n (1 ≤ n ≤ 200,000) nodes and a list of q (1 ≤ q ≤ 100,000) queries, process the queries in order and out

【bzoj3589】动态树 树链剖分+线段树

题目描述 别忘了这是一棵动态树, 每时每刻都是动态的. 小明要求你在这棵树上维护两种事件 事件0:这棵树长出了一些果子, 即某个子树中的每个节点都会长出K个果子. 事件1:小明希望你求出几条树枝上的果子数. 一条树枝其实就是一个从某个节点到根的路径的一段. 每次小明会选定一些树枝, 让你求出在这些树枝上的节点的果子数的和. 注意, 树枝之间可能会重合, 这时重合的部分的节点的果子只要算一次. 输入 第一行一个整数n(1<=n<=200,000), 即节点数. 接下来n-1行, 每行两个数字u,

BZOJ2243 (树链剖分+线段树)

Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. 解题分析 树链剖分+线段树. 开一个记录类型,记录某一段区间的信息.l 表示区间最左侧的颜色 , r 表示区间最右侧的颜色 , sum 表示区间中颜色段数量. 合并时判断一下左区间的右端点和有区间的左端点的颜色是否一样. 树上合并时需要用两个变量ans1,ans2来存储.ans1表示x往上走时形成的链的信息,

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

【BZOJ】1146: [CTSC2008]网络管理Network(树链剖分+线段树套平衡树+二分 / dfs序+树状数组+主席树)

第一种做法(时间太感人): 这题我真的逗了,调了一下午,疯狂造数据,始终找不到错. 后来发现自己sb了,更新那里没有打id,直接套上u了.我.... 调了一下午啊!一下午的时光啊!本来说好中午A掉去学习第二种做法,噗 好吧,现在第一种做法是hld+seg+bst+二分,常数巨大,log^4级别,目前只会这种. 树剖后仍然用线段树维护dfs序区间,然后在每个区间建一颗平衡树,我用treap,(这题找最大啊,,,囧,并且要注意,这里的rank是比他大的数量,so,我们在二分时判断要判断一个范围,即要