树链剖分第一发HDU 3966

好几周之前学长讲了树链剖分(ps:我记得讲的时间超级短,大概不到二十分钟就讲完了~_~,那时候学长说好简单,,,,现在看起来确实不是很难)

HDU 3966

题意:

  给了一个树和各个点的权值,不超过五万个点,有以下三种操作,操作数不超过十万

  I a b w :(I是字符"I",a,b,w是数字)表示从 a 到 b 的路径上的点的权值都加上 w

  D a b w :从 a 到 b 的路径上的点的权值都减去 w

  Q a : 询问点 a 的权值是多少

这是一个树链剖分的裸题~笨宝宝wa(MLE,TLE,RE)了好多好多次~~~

树链剖分参考博客 呜呜呜~这篇博客非常棒~尤其是他的例子的那个图

莫名其妙的超空间

莫名其妙的超时

re是因为数组开小了~

附代码:

  1 #pragma comment(linker, "/STACK:1024000000,1024000000")
  2 #include <iostream>
  3 #include <stdio.h>
  4 #include <stdlib.h>
  5 #include <cstring>
  6 #include <algorithm>
  7 using namespace std ;
  8 #define LL long long
  9 #define rep(i,n) for (int i = 1 ; i <= n ; ++ i)
 10
 11 const int maxn = 100010 ;
 12 int N , R , QAQ , h[maxn] , to[maxn] , nxt[maxn] , val[maxn] , cnt , id ;
 13 int dep[maxn] , siz[maxn] , son[maxn] , fa[maxn] ;
 14 int top[maxn] , pos[maxn] , rk[maxn] ;
 15 void Init()
 16 {
 17     memset(h,-1,sizeof(h)) ;
 18     memset(son,-1,sizeof(son)) ;
 19     cnt = id = 0 ;
 20     fa[1] = 1 ;
 21 }
 22
 23 inline void addedge(int u,int v)
 24 {
 25     to[cnt] = v , nxt[cnt] = h[u] , h[u] = cnt ++ ;
 26     to[cnt] = u , nxt[cnt] = h[v] , h[v] = cnt ++ ;
 27 }
 28 void dfsa(int rt,int d)
 29 {
 30     dep[rt] = d , siz[rt] = 1 ;
 31     int v ;
 32     for (int i = h[rt] ; ~i ; i = nxt[i]) {
 33         v = to[i] ;
 34         if (v != fa[rt]) {
 35             fa[v] = rt ;
 36             dfsa(v,d+1) ;
 37             siz[rt] += siz[v] ;
 38             if (son[rt] == -1 || siz[v] > siz[son[rt]]) son[rt] = v ;
 39         }
 40     }
 41 }
 42
 43 void dfsb(int rt,int tp)
 44 {
 45     pos[rt] = ++ id ;
 46     top[rt] = tp ;
 47     rk[pos[rt]] = rt ;
 48     if (son[rt] == -1) return ;
 49     dfsb(son[rt],tp) ;
 50     int v ;
 51     for (int i = h[rt] ; ~i ; i = nxt[i]) {
 52         v = to[i] ;
 53         if (v != fa[rt] && v != son[rt]) dfsb(v,v) ;
 54     }
 55 }
 56
 57 struct Node
 58 {
 59     int le , ri , x , tag ;
 60 }A[maxn<<2];
 61
 62 void Build(int i,int le,int ri)
 63 {
 64     A[i].le = le , A[i].ri = ri ;
 65     A[i].tag = A[i].x = 0 ;
 66     if (le == ri) {
 67         A[i].x = val[rk[le]] ;
 68         return ;
 69     }
 70     int mid = (le+ri)>>1 ;
 71     Build(i<<1,le,mid) ;
 72     Build(i<<1|1,mid+1,ri) ;
 73 }
 74
 75 void pushDown(int i)
 76 {
 77     if (A[i].tag) {
 78         A[i<<1].tag += A[i].tag ;
 79         A[i<<1].x += A[i].tag ;
 80         A[i<<1|1].tag += A[i].tag ;
 81         A[i<<1|1].x += A[i].tag ;
 82         A[i].tag = 0 ;
 83     }
 84 }
 85
 86 void update(int i,int le,int ri,int x)
 87 {
 88     if (le < A[i].le || ri > A[i].ri) return ;
 89     if (A[i].le == le && A[i].ri == ri) {
 90         A[i].tag += x , A[i].x += x ;
 91         return ;
 92     }
 93     pushDown(i) ;
 94     int mid = (A[i].le + A[i].ri)>>1 ;
 95     if (ri <= mid) update(i<<1,le,ri,x) ;
 96     else if (le > mid) update(i<<1|1,le,ri,x) ;
 97     else {
 98         update(i<<1,le,mid,x) ;
 99         update(i<<1|1,mid+1,ri,x) ;
100     }
101 }
102
103 int Query(int i,int p)
104 {
105     if (A[i].le == p && A[i].ri == p) return A[i].x ;
106     pushDown(i) ;
107     int mid = (A[i].le + A[i].ri)>>1 ;
108     if (p <= mid) return Query(i<<1,p) ;
109     else return Query(i<<1|1,p) ;
110 }
111
112 void solveUpdate(int u,int v,int w)
113 {
114     while (top[u] != top[v]) {
115         if (dep[top[u]] < dep[top[v]]) swap(u,v) ;
116         update(1,pos[top[u]],pos[u],w) ;
117         u = fa[top[u]] ;
118     }
119     if (dep[u] > dep[v]) swap(u,v) ;
120     update(1,pos[u],pos[v],w) ;
121 }
122
123 int main()
124 {
125  //   freopen("in.txt","r",stdin) ;
126     int u , v , w ;
127     char c ;
128     while (scanf("%d%d%d",&N,&R,&QAQ) == 3) {
129         Init() ;
130         rep(i,N) scanf("%d",&val[i]) ;
131         rep(i,R) {
132             scanf("%d%d",&u,&v) ;
133             addedge(u,v) ;
134         }
135         dfsa(1,1) ;
136         dfsb(1,1) ;
137         Build(1,1,N) ;
138         while (QAQ --) {
139             c = getchar() ;
140             while (c != ‘I‘ && c != ‘D‘ && c != ‘Q‘) c = getchar() ;
141             if (c == ‘Q‘) {
142                 scanf("%d",&w) ;
143                 printf("%d\n",Query(1,pos[w])) ;
144             }
145             else {
146                 scanf("%d%d%d",&u,&v,&w) ;
147                 if (c == ‘D‘) w = -w ;
148                 solveUpdate(u,v,w) ;
149             }
150         }
151     }
152     return 0 ;
153 }

hdu3966

~end~

时间: 2024-10-11 13:18:32

树链剖分第一发HDU 3966的相关文章

树链刨分 HDU 3966

树 n个点 m条边(其实就是n-1) q个询问 a1 a2 a3 ... 这些节点开始的人 I  a b c   a->b  这条链上的都加c D    ...                             减 q  a 查询节点a上的人 具体看代码上的注释 #include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define MAXN 50010 st

【AC自动机+树链剖分】HDU 5566

离线做法 对给出的树作树剖 把每个询问区间先加入线段树的结点 后对线段树每个有询问的节点建立AC自动机 对每个节点单独询问 1 // #include <bits/stdc++.h> 2 #include <iostream> 3 #include <cstdio> 4 #include <queue> 5 #include <cstring> 6 #include <cctype> 7 #include <algorithm&

SPOJ 375 QTREE系列-Query on a tree (树链剖分)

题目地址:SPOJ 375 树链剖分第一发! 果然是个貌似很高级的数据结构,其实就是把树的边从树形结构转化成了线性结构,从而可以用线段树或树状数组之类的数据结构进行快速维护.从而将时间缩到n*log(2*n). 这题用的线段树维护的. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #incl

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(树链剖分 模板题)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3966 Problem Description Our protagonist is the handsome human prince Aragorn comes from The Lord of the Rings. One day Aragorn finds a lot of enemies who want to invade his kingdom. As Aragorn knows, th

树链剖分 [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): 3544    Accepted Submission(s): 995 Problem Description Our protagonist is the handsome human prince Aragorn comes from The Lord

HDU 3966 Aragorn&amp;#39;s Story(树链剖分)

HDU Aragorn's Story 题目链接 树抛入门裸题,这题是区间改动单点查询,于是套树状数组就OK了 代码: #include <cstdio> #include <cstring> #include <vector> #include <algorithm> using namespace std; const int N = 50005; inline int lowbit(int x) {return x&(-x);} int dep

HDU 3966 Aragorn&#39;s Story 树链剖分

Link: http://acm.hdu.edu.cn/showproblem.php?pid=3966 这题注意要手动扩栈. 这题我交g++无限RE,即使手动扩栈了,但交C++就过了. 1 #pragma comment(linker, "/STACK:1024000000,1024000000") 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 #include &

HDU 3966(树链剖分+点修改+点查询)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3966 题目大意:营地的分布成树型.每个营地都有一些人,每次修改修改一条链上的所有营地的人数,每次查询单个点. 解题思路: 树链剖分基础题. 维护一个sum. 注意轻链修改时,点修改和边修改的不同. 由于树的结构与线段树点的顺序不太相同,因此需要做一个映射数组rank.故在线段树Build的时候,权值是camp[rank[l]],rank这步的映射在dfs2的时候完成,rank[w[u]]=u; Qu