hdu5044 Tree 树链拆分。点细分。刚,非递归版本

  1. //#pragma warning (disable: 4786)
  2. //#pragma comment (linker, "/STACK:16777216")
  3. //#pragma comment(linker, "/STACK:60400000,60400000")
  4.  
  5. //HEAD
  6. #include <cstdio>
  7. #include <ctime>
  8. #include <cstdlib>
  9. #include <cstring>
  10. #include <queue>
  11. #include <string>
  12. #include <set>
  13. #include <stack>
  14. #include <map>
  15. #include <cmath>
  16. #include <vector>
  17. #include <iostream>
  18. #include <algorithm>
  19. using namespace std;
  20. //LOOP
  21. #define FE(i, a, b) for(int i = (a); i <= (b); ++i)
  22. #define FD(i, b, a) for(int i = (b); i>= (a); --i)
  23. #define REP(i, N) for(int i = 0; i < (N); ++i)
  24. #define CLR(A,value) memset(A,value,sizeof(A))
  25. #define CPY(a, b) memcpy(a, b, sizeof(a))
  26. #define FC(it, c) for(__typeof((c).begin()) it = (c).begin(); it != (c).end(); it++)
  27. //INPUT
  28. #define RI(n) scanf("%d", &n)
  29. #define RII(n, m) scanf("%d%d", &n, &m)
  30. #define RIII(n, m, k) scanf("%d%d%d", &n, &m, &k)
  31. #define RS(s) scanf("%s", s)
  32. //OUTPUT
  33. #define WI(n) printf("%d\n", n)
  34. #define WS(s) printf("%s\n", s)
  35.  
  36. typedef long long LL;
  37. const int INF = 1000000007;
  38. const double eps = 1e-10;
  39.  
  40. const int MAXN = 100020;
  41.  
  42. int n;
  43.  
  44. int e[MAXN][2];
  45. int idx_e[MAXN];
  46. int ans_e[MAXN];
  47.  
  48. struct Edge{
  49. int to, next;
  50. };
  51. Edge adj[MAXN * 2];
  52. int head[MAXN], tol;
  53. int hd[MAXN];
  54.  
  55. int top[MAXN];///top[v]表示v所在重链的顶端定点
  56. int fa[MAXN];///fa[v]表示v的父节点,没有为-1
  57. int deep[MAXN];///deep[v]表示v在树中的深度,根点为1
  58. int num[MAXN];///num[v]表示以v为根的子树的节点数
  59.  
  60. int son[MAXN];///重儿子,没有为-1
  61. int p[MAXN];///p[v]表示v和其父亲节点的连边在线段树的位置(标号)
  62.  
  63. int point_p[MAXN];
  64. int point_pos;
  65.  
  66. int pos;
  67.  
  68. inline void init()
  69. {
  70. tol = 0;///init_edge
  71. //CLR(head, -1);
  72. for (int i = 0; i <= n + 10; i++) head[i] = -1, son[i] = -1;
  73.  
  74. pos = 0;///init_p
  75. //CLR(son, -1);
  76.  
  77. point_pos = 0;
  78. }
  79. inline void add_edge(int u, int v)
  80. {
  81. adj[tol].to = v;
  82. adj[tol].next = head[u];
  83. head[u] = tol++;
  84. }
  85.  
  86. void dfs1(int u, int pre, int d)///求出fa, deep, num, son
  87. {
  88. deep[u] = d;
  89. fa[u] = pre;
  90. num[u] = 1;
  91.  
  92. for (int r = head[u]; r != -1; r = adj[r].next)
  93. {
  94. int v = adj[r].to;
  95. if (v != pre)
  96. {
  97. dfs1(v, u, d + 1);
  98. num[u] += num[v];
  99. if (son[u] == -1 || num[v] > num[son[u]])
  100. son[u] = v;
  101. }
  102. }
  103. }
  104.  
  105. struct sknode{
  106. int u, pre, d;
  107. sknode(){}
  108. sknode(int u, int pre, int d):u(u), pre(pre), d(d)
  109. {
  110. }
  111. };
  112. int fir[MAXN];
  113. void bfs1()
  114. {
  115. stack<sknode>sk;
  116. for (int i = 0; i <= n + 10; i++) hd[i] = head[i], fir[i] = 0;
  117.  
  118. sk.push(sknode(1, -1, 1));
  119. while (!sk.empty())
  120. {
  121. sknode sku = sk.top();
  122. int u = sku.u, d = sku.d, pre = sku.pre;
  123. int r = hd[u];
  124. if (!fir[u])
  125. {
  126. fir[u] = 1;
  127. deep[u] = d;
  128. fa[u] = pre;
  129. num[u] = 1;
  130. }
  131. if (r == -1)
  132. {
  133. if (pre != -1)
  134. {
  135. num[pre] += num[u];
  136. if (son[pre] == -1 || num[u] > num[son[pre]])
  137. son[pre] = u;
  138. }
  139. sk.pop();
  140. }
  141. else
  142. {
  143. int v = adj[r].to;
  144. if (v != pre)
  145. {
  146. sk.push(sknode(v, u, d +1));
  147. }
  148. hd[u] = adj[r].next;
  149. }
  150. }
  151. }
  152.  
  153. void getpos(int u, int sp)///top, p, fp
  154. {
  155. top[u] = sp;
  156. p[u] = ++pos;
  157. ans_e[ idx_e[u] ] = pos;
  158. point_p[u] = ++point_pos;
  159.  
  160. if (son[u] != -1)
  161. getpos(son[u], sp);
  162. else return ;
  163. for (int r = head[u]; r != -1; r = adj[r].next)
  164. {
  165. int v = adj[r].to;
  166. if (v != son[u] && v != fa[u])
  167. getpos(v, v);
  168. }
  169. }
  170. struct node{
  171. int u, sp;
  172. node(){}
  173. node(int u, int sp):u(u), sp(sp){}
  174. };
  175. void bfs2()
  176. {
  177. stack<node> sk;
  178. for (int i = 0; i <= n + 10; i++) hd[i] = head[i], fir[i] = 0;
  179. sk.push(node(1, 1));
  180.  
  181. while (!sk.empty())
  182. {
  183. node sku = sk.top();
  184. int u = sku.u, sp = sku.sp;
  185. int r = hd[u];
  186. if (!fir[u])
  187. {
  188. fir[u] = 1;
  189. top[u] = sp;
  190. p[u] = ++pos;
  191. ans_e[ idx_e[u] ] = pos;
  192. point_p[u] = ++point_pos;
  193.  
  194. if (son[u] != -1)
  195. {
  196. sk.push(node(son[u], sp));
  197. }
  198. else
  199. {
  200. sk.pop();
  201. }
  202. continue;
  203. }
  204. if (r == -1)
  205. {
  206. sk.pop();
  207. }
  208. else
  209. {
  210. int v = adj[r].to;
  211. if (v != son[u] && v != fa[u])
  212. {
  213. sk.push(node(v, v));
  214. }
  215. hd[u] = adj[r].next;
  216. }
  217. }
  218. }
  219.  
  220. ///
  221. LL sum[2][MAXN];
  222. inline int lowbit(int x)
  223. {
  224. return x & (-x);
  225. }
  226. inline void add(int i, int x, int op)
  227. {
  228. for (; i <= n + 10; i += lowbit(i))
  229. {
  230. sum[op][i] += x;
  231. }
  232. }
  233. inline LL getsum(int i, int op)
  234. {
  235. LL ret = 0;
  236. for (; i > 0; i -= lowbit(i))
  237. ret += sum[op][i];
  238. return ret;
  239. }
  240.  
  241. inline void update(int u, int v, int val, int op)
  242. {
  243. int fu = top[u];
  244. int fv = top[v];
  245.  
  246. while (fu != fv)
  247. {
  248. if (deep[fu] < deep[fv])
  249. {
  250. swap(fu, fv);
  251. swap(u, v);
  252. }
  253.  
  254. add(p[fu], val, op);
  255. add(p[u] + 1, -val, op);
  256.  
  257. u = fa[fu]; fu = top[u];
  258. }
  259. if (u == v) return ;
  260. if (deep[u] > deep[v]) swap(u, v);
  261.  
  262. add(p[son[u]], val, op);
  263. add(p[v] + 1, -val, op);
  264. ///假设是点剖分的话query(p[u], p[v], 1, pos, 1)
  265. }
  266.  
  267. inline void point_update(int u, int v, int val, int op)
  268. {
  269. int fu = top[u];
  270. int fv = top[v];
  271.  
  272. while (fu != fv)
  273. {
  274. if (deep[fu] < deep[fv])
  275. {
  276. swap(fu, fv);
  277. swap(u, v);
  278. }
  279.  
  280. //cout << point_p[fu] << ' ' << point_p[u] <<endl;
  281.  
  282. add(point_p[fu], val, op);
  283. add(point_p[u] + 1, -val, op);
  284.  
  285. u = fa[fu]; fu = top[u];
  286. }
  287. if (deep[u] > deep[v]) swap(u, v);
  288. //cout << point_p[u] << ' ' << point_p[v] <<endl;
  289.  
  290. add(point_p[u], val, op);
  291. add(point_p[v] + 1, -val, op);
  292. ///假设是点剖分的话query(p[u], p[v], 1, pos, 1)
  293. }
  294.  
  295. char cc;
  296. inline void read(int &ret)
  297. {
  298. ret = 0;
  299. cc = getchar();
  300. while (cc < '0' || cc > '9') cc = getchar();
  301. while (cc >= '0' && cc <= '9')
  302. {
  303. ret = (ret << 3) + (ret << 1) + cc - '0';
  304. cc = getchar();
  305. }
  306. }
  307. inline void out(LL ret)
  308. {
  309. if (ret > 9) out(ret / 10);
  310. putchar(ret % 10 + '0');
  311. }
  312.  
  313. int main ()
  314. {
  315. char op[10];
  316. int T, Q;
  317. int ncase = 1;
  318. int u, v;
  319. int x, y, z;
  320. read(T);
  321. while (T--)
  322. {
  323. init();
  324. //RII(n, Q);
  325. read(n); read(Q);
  326. FE(i, 1, n - 1)
  327. {
  328. read(e[i][0]); read(e[i][1]);
  329. //RII(e[i][0], e[i][1]);
  330. add_edge(e[i][0], e[i][1]);
  331. add_edge(e[i][1], e[i][0]);
  332. }
  333. bfs1();
  334. //puts("***********");
  335. //dfs1(1, -1, 1);
  336. FE(i, 1, n - 1)
  337. {
  338. if (deep[e[i][0]] > deep[e[i][1]])
  339. swap(e[i][0], e[i][1]);
  340. idx_e[e[i][1]] = i;
  341. }
  342. bfs2();
  343. //puts("***********");
  344. //getpos(1, 1);
  345.  
  346. for (int i = 0; i <= n + 10; i++) sum[0][i] = sum[1][i] = 0;
  347. //CLR(sum, 0);///初始化
  348.  
  349. while (Q--)
  350. {
  351. scanf("%s", op);
  352. read(x); read(y); read(z);
  353. //scanf("%d%d%d", &x, &y, &z);
  354. if (op[3] == '1')
  355. {
  356. //puts("***********");
  357.  
  358. point_update(x, y, z, 0);
  359. }
  360. else
  361. {
  362. update(x, y, z, 1);
  363. }
  364. }
  365.  
  366. printf("Case #%d:\n", ncase++);
  367. for (int i = 1; i <= n; i++)
  368. {
  369. out(getsum(point_p[i], 0));
  370. //printf("%I64d", getsum(point_p[i], 0));
  371. //printf("%I64d", getsum(point_p[i], 0));
  372. if (i == n) printf("\n");
  373. else printf(" ");
  374. }
  375. if (n == 1) printf("\n");
  376. else
  377. for (int i = 1; i < n; i++)
  378. {
  379. //printf("%I64d", getsum(mp[make_pair(e[i][1], e[i][0])], 1));
  380. out( getsum(ans_e[i], 1) );
  381. //printf("%I64d", getsum(ans_e[i], 1));
  382. if (i == n - 1) printf("\n");
  383. else printf(" ");
  384. }
  385. }
  386. return 0;
  387. }

版权声明:本文博主原创文章,博客,未经同意不得转载。

hdu5044 Tree 树链拆分,点细分,刚,非递归版本的更多相关文章

  1. poj 3237 Tree(树链拆分)

    题目链接:poj 3237 Tree 题目大意:给定一棵树,三种操作: CHANGE i v:将i节点权值变为v NEGATE a b:将ab路径上全部节点的权值变为相反数 QUERY a b:查询a ...

  2. hdu 4912 Paths on the tree(树链拆分+贪婪)

    题目链接:hdu 4912 Paths on the tree 题目大意:给定一棵树,和若干个通道.要求尽量选出多的通道,而且两两通道不想交. 解题思路:用树链剖分求LCA,然后依据通道两端节点的LC ...

  3. 数据结构--Avl树的创建,插入的递归版本和非递归版本,删除等操作

    AVL树本质上还是一棵二叉搜索树,它的特点是: 1.本身首先是一棵二叉搜索树.   2.带有平衡条件:每个结点的左右子树的高度之差的绝对值最多为1(空树的高度为-1).   也就是说,AVL树,本质上 ...

  4. Hdu 5274 Dylans loves tree (树链剖分模板)

    Hdu 5274 Dylans loves tree (树链剖分模板) 题目传送门 #include <queue> #include <cmath> #include < ...

  5. POJ3237 Tree 树链剖分 边权

    POJ3237 Tree 树链剖分 边权 传送门:http://poj.org/problem?id=3237 题意: n个点的,n-1条边 修改单边边权 将a->b的边权取反 查询a-> ...

  6. POJ 3237 Tree (树链拆分)

    主题链接~~> 做题情绪:了. 解题思路: 主要注意如何区间更新就ok了 . 树链剖分就是树上的线段树. 代码: #include<iostream> #include<sst ...

  7. poj 3237 Tree 树链剖分

    题目链接:http://poj.org/problem?id=3237 You are given a tree with N nodes. The tree’s nodes are numbered ...

  8. Query on a tree——树链剖分整理

    树链剖分整理 树链剖分就是把树拆成一系列链,然后用数据结构对链进行维护. 通常的剖分方法是轻重链剖分,所谓轻重链就是对于节点u的所有子结点v,size[v]最大的v与u的边是重边,其它边是轻边,其中s ...

  9. 【BZOJ-4353】Play with tree 树链剖分

    4353: Play with tree Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 31  Solved: 19[Submit][Status][ ...

随机推荐

  1. table 谷歌下不出现滚动条

    <table> </table> <style> table {overflow-y:scroll;max-height:152px; height:auto;} ...

  2. C日常语言实践中小(四)——勇者斗恶龙

    勇者斗恶龙 愿你的国有n龙的头,你想聘请骑士杀死它(全部的头). 村里有m个骑士能够雇佣,一个能力值为x的骑士能够砍掉恶龙一个致敬不超过x的头,且须要支付x个金币. 怎样雇佣骑士才干砍掉恶龙的全部头, ...

  3. linux input如何固定设备event handler

    于qt开发时间.遇到的问题,usb输入设备(鼠标器,usb 电容屏)在动力分配后自己主动input节点,实例usb鼠标停留电后,分配给自己的主动性/dev/input/event0 mouse0.第一 ...

  4. 文章13称号 Add Two Numbers

    You are given two linked lists representing two non-negative numbers. The digits are stored in rever ...

  5. Python 摘录LinkedIn用户联系人

    CODE: #!/usr/bin/python # -*- coding: utf-8 -*- ''' Created on 2014-8-18 @author: guaguastd @name: l ...

  6. SPOJ 15. The Shortest Path 堆优化Dijsktra

    You are given a list of cities. Each direct connection between two cities has its transportation cos ...

  7. POJ1149 PIGS 【最大流量】

    PIGS Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 16555   Accepted: 7416 Description ...

  8. android代码签名和混乱的包装

    研究了一下android的apk困惑签名和代码包装,假设没有混乱包.然后apk人们可以直接查看源代码反编译出来,尽管混乱包或能看懂.但不是那么容易理解,要求在至少一些时间 假设不混淆,反编译后的代码例 ...

  9. leaflet开源地图库源码 浏览器&移动设备判断(browser.js)备份

    <script> var isIe = !-[1,]; // alert('ie9 之前'+isIe); var ie = 'ActiveXObject' in window; //ale ...

  10. Android-往来:添加到联系人

    //添加到联系人.使用事务 public void testAddContact() { String name[]={"周杰伦","谢霆锋","言承 ...