hdu5044 Tree 树链拆分,点细分,刚,非递归版本
hdu5044 Tree 树链拆分。点细分。刚,非递归版本
- //#pragma warning (disable: 4786)
- //#pragma comment (linker, "/STACK:16777216")
- //#pragma comment(linker, "/STACK:60400000,60400000")
- //HEAD
- #include <cstdio>
- #include <ctime>
- #include <cstdlib>
- #include <cstring>
- #include <queue>
- #include <string>
- #include <set>
- #include <stack>
- #include <map>
- #include <cmath>
- #include <vector>
- #include <iostream>
- #include <algorithm>
- using namespace std;
- //LOOP
- #define FE(i, a, b) for(int i = (a); i <= (b); ++i)
- #define FD(i, b, a) for(int i = (b); i>= (a); --i)
- #define REP(i, N) for(int i = 0; i < (N); ++i)
- #define CLR(A,value) memset(A,value,sizeof(A))
- #define CPY(a, b) memcpy(a, b, sizeof(a))
- #define FC(it, c) for(__typeof((c).begin()) it = (c).begin(); it != (c).end(); it++)
- //INPUT
- #define RI(n) scanf("%d", &n)
- #define RII(n, m) scanf("%d%d", &n, &m)
- #define RIII(n, m, k) scanf("%d%d%d", &n, &m, &k)
- #define RS(s) scanf("%s", s)
- //OUTPUT
- #define WI(n) printf("%d\n", n)
- #define WS(s) printf("%s\n", s)
- typedef long long LL;
- const int INF = 1000000007;
- const double eps = 1e-10;
- const int MAXN = 100020;
- int n;
- int e[MAXN][2];
- int idx_e[MAXN];
- int ans_e[MAXN];
- struct Edge{
- int to, next;
- };
- Edge adj[MAXN * 2];
- int head[MAXN], tol;
- int hd[MAXN];
- int top[MAXN];///top[v]表示v所在重链的顶端定点
- int fa[MAXN];///fa[v]表示v的父节点,没有为-1
- int deep[MAXN];///deep[v]表示v在树中的深度,根点为1
- int num[MAXN];///num[v]表示以v为根的子树的节点数
- int son[MAXN];///重儿子,没有为-1
- int p[MAXN];///p[v]表示v和其父亲节点的连边在线段树的位置(标号)
- int point_p[MAXN];
- int point_pos;
- int pos;
- inline void init()
- {
- tol = 0;///init_edge
- //CLR(head, -1);
- for (int i = 0; i <= n + 10; i++) head[i] = -1, son[i] = -1;
- pos = 0;///init_p
- //CLR(son, -1);
- point_pos = 0;
- }
- inline void add_edge(int u, int v)
- {
- adj[tol].to = v;
- adj[tol].next = head[u];
- head[u] = tol++;
- }
- void dfs1(int u, int pre, int d)///求出fa, deep, num, son
- {
- deep[u] = d;
- fa[u] = pre;
- num[u] = 1;
- for (int r = head[u]; r != -1; r = adj[r].next)
- {
- int v = adj[r].to;
- if (v != pre)
- {
- dfs1(v, u, d + 1);
- num[u] += num[v];
- if (son[u] == -1 || num[v] > num[son[u]])
- son[u] = v;
- }
- }
- }
- struct sknode{
- int u, pre, d;
- sknode(){}
- sknode(int u, int pre, int d):u(u), pre(pre), d(d)
- {
- }
- };
- int fir[MAXN];
- void bfs1()
- {
- stack<sknode>sk;
- for (int i = 0; i <= n + 10; i++) hd[i] = head[i], fir[i] = 0;
- sk.push(sknode(1, -1, 1));
- while (!sk.empty())
- {
- sknode sku = sk.top();
- int u = sku.u, d = sku.d, pre = sku.pre;
- int r = hd[u];
- if (!fir[u])
- {
- fir[u] = 1;
- deep[u] = d;
- fa[u] = pre;
- num[u] = 1;
- }
- if (r == -1)
- {
- if (pre != -1)
- {
- num[pre] += num[u];
- if (son[pre] == -1 || num[u] > num[son[pre]])
- son[pre] = u;
- }
- sk.pop();
- }
- else
- {
- int v = adj[r].to;
- if (v != pre)
- {
- sk.push(sknode(v, u, d +1));
- }
- hd[u] = adj[r].next;
- }
- }
- }
- void getpos(int u, int sp)///top, p, fp
- {
- top[u] = sp;
- p[u] = ++pos;
- ans_e[ idx_e[u] ] = pos;
- point_p[u] = ++point_pos;
- if (son[u] != -1)
- getpos(son[u], sp);
- else return ;
- for (int r = head[u]; r != -1; r = adj[r].next)
- {
- int v = adj[r].to;
- if (v != son[u] && v != fa[u])
- getpos(v, v);
- }
- }
- struct node{
- int u, sp;
- node(){}
- node(int u, int sp):u(u), sp(sp){}
- };
- void bfs2()
- {
- stack<node> sk;
- for (int i = 0; i <= n + 10; i++) hd[i] = head[i], fir[i] = 0;
- sk.push(node(1, 1));
- while (!sk.empty())
- {
- node sku = sk.top();
- int u = sku.u, sp = sku.sp;
- int r = hd[u];
- if (!fir[u])
- {
- fir[u] = 1;
- top[u] = sp;
- p[u] = ++pos;
- ans_e[ idx_e[u] ] = pos;
- point_p[u] = ++point_pos;
- if (son[u] != -1)
- {
- sk.push(node(son[u], sp));
- }
- else
- {
- sk.pop();
- }
- continue;
- }
- if (r == -1)
- {
- sk.pop();
- }
- else
- {
- int v = adj[r].to;
- if (v != son[u] && v != fa[u])
- {
- sk.push(node(v, v));
- }
- hd[u] = adj[r].next;
- }
- }
- }
- ///
- LL sum[2][MAXN];
- inline int lowbit(int x)
- {
- return x & (-x);
- }
- inline void add(int i, int x, int op)
- {
- for (; i <= n + 10; i += lowbit(i))
- {
- sum[op][i] += x;
- }
- }
- inline LL getsum(int i, int op)
- {
- LL ret = 0;
- for (; i > 0; i -= lowbit(i))
- ret += sum[op][i];
- return ret;
- }
- inline void update(int u, int v, int val, int op)
- {
- int fu = top[u];
- int fv = top[v];
- while (fu != fv)
- {
- if (deep[fu] < deep[fv])
- {
- swap(fu, fv);
- swap(u, v);
- }
- add(p[fu], val, op);
- add(p[u] + 1, -val, op);
- u = fa[fu]; fu = top[u];
- }
- if (u == v) return ;
- if (deep[u] > deep[v]) swap(u, v);
- add(p[son[u]], val, op);
- add(p[v] + 1, -val, op);
- ///假设是点剖分的话query(p[u], p[v], 1, pos, 1)
- }
- inline void point_update(int u, int v, int val, int op)
- {
- int fu = top[u];
- int fv = top[v];
- while (fu != fv)
- {
- if (deep[fu] < deep[fv])
- {
- swap(fu, fv);
- swap(u, v);
- }
- //cout << point_p[fu] << ' ' << point_p[u] <<endl;
- add(point_p[fu], val, op);
- add(point_p[u] + 1, -val, op);
- u = fa[fu]; fu = top[u];
- }
- if (deep[u] > deep[v]) swap(u, v);
- //cout << point_p[u] << ' ' << point_p[v] <<endl;
- add(point_p[u], val, op);
- add(point_p[v] + 1, -val, op);
- ///假设是点剖分的话query(p[u], p[v], 1, pos, 1)
- }
- char cc;
- inline void read(int &ret)
- {
- ret = 0;
- cc = getchar();
- while (cc < '0' || cc > '9') cc = getchar();
- while (cc >= '0' && cc <= '9')
- {
- ret = (ret << 3) + (ret << 1) + cc - '0';
- cc = getchar();
- }
- }
- inline void out(LL ret)
- {
- if (ret > 9) out(ret / 10);
- putchar(ret % 10 + '0');
- }
- int main ()
- {
- char op[10];
- int T, Q;
- int ncase = 1;
- int u, v;
- int x, y, z;
- read(T);
- while (T--)
- {
- init();
- //RII(n, Q);
- read(n); read(Q);
- FE(i, 1, n - 1)
- {
- read(e[i][0]); read(e[i][1]);
- //RII(e[i][0], e[i][1]);
- add_edge(e[i][0], e[i][1]);
- add_edge(e[i][1], e[i][0]);
- }
- bfs1();
- //puts("***********");
- //dfs1(1, -1, 1);
- FE(i, 1, n - 1)
- {
- if (deep[e[i][0]] > deep[e[i][1]])
- swap(e[i][0], e[i][1]);
- idx_e[e[i][1]] = i;
- }
- bfs2();
- //puts("***********");
- //getpos(1, 1);
- for (int i = 0; i <= n + 10; i++) sum[0][i] = sum[1][i] = 0;
- //CLR(sum, 0);///初始化
- while (Q--)
- {
- scanf("%s", op);
- read(x); read(y); read(z);
- //scanf("%d%d%d", &x, &y, &z);
- if (op[3] == '1')
- {
- //puts("***********");
- point_update(x, y, z, 0);
- }
- else
- {
- update(x, y, z, 1);
- }
- }
- printf("Case #%d:\n", ncase++);
- for (int i = 1; i <= n; i++)
- {
- out(getsum(point_p[i], 0));
- //printf("%I64d", getsum(point_p[i], 0));
- //printf("%I64d", getsum(point_p[i], 0));
- if (i == n) printf("\n");
- else printf(" ");
- }
- if (n == 1) printf("\n");
- else
- for (int i = 1; i < n; i++)
- {
- //printf("%I64d", getsum(mp[make_pair(e[i][1], e[i][0])], 1));
- out( getsum(ans_e[i], 1) );
- //printf("%I64d", getsum(ans_e[i], 1));
- if (i == n - 1) printf("\n");
- else printf(" ");
- }
- }
- return 0;
- }
版权声明:本文博主原创文章,博客,未经同意不得转载。
hdu5044 Tree 树链拆分,点细分,刚,非递归版本的更多相关文章
- poj 3237 Tree(树链拆分)
题目链接:poj 3237 Tree 题目大意:给定一棵树,三种操作: CHANGE i v:将i节点权值变为v NEGATE a b:将ab路径上全部节点的权值变为相反数 QUERY a b:查询a ...
- hdu 4912 Paths on the tree(树链拆分+贪婪)
题目链接:hdu 4912 Paths on the tree 题目大意:给定一棵树,和若干个通道.要求尽量选出多的通道,而且两两通道不想交. 解题思路:用树链剖分求LCA,然后依据通道两端节点的LC ...
- 数据结构--Avl树的创建,插入的递归版本和非递归版本,删除等操作
AVL树本质上还是一棵二叉搜索树,它的特点是: 1.本身首先是一棵二叉搜索树. 2.带有平衡条件:每个结点的左右子树的高度之差的绝对值最多为1(空树的高度为-1). 也就是说,AVL树,本质上 ...
- Hdu 5274 Dylans loves tree (树链剖分模板)
Hdu 5274 Dylans loves tree (树链剖分模板) 题目传送门 #include <queue> #include <cmath> #include < ...
- POJ3237 Tree 树链剖分 边权
POJ3237 Tree 树链剖分 边权 传送门:http://poj.org/problem?id=3237 题意: n个点的,n-1条边 修改单边边权 将a->b的边权取反 查询a-> ...
- POJ 3237 Tree (树链拆分)
主题链接~~> 做题情绪:了. 解题思路: 主要注意如何区间更新就ok了 . 树链剖分就是树上的线段树. 代码: #include<iostream> #include<sst ...
- poj 3237 Tree 树链剖分
题目链接:http://poj.org/problem?id=3237 You are given a tree with N nodes. The tree’s nodes are numbered ...
- Query on a tree——树链剖分整理
树链剖分整理 树链剖分就是把树拆成一系列链,然后用数据结构对链进行维护. 通常的剖分方法是轻重链剖分,所谓轻重链就是对于节点u的所有子结点v,size[v]最大的v与u的边是重边,其它边是轻边,其中s ...
- 【BZOJ-4353】Play with tree 树链剖分
4353: Play with tree Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 31 Solved: 19[Submit][Status][ ...
随机推荐
- table 谷歌下不出现滚动条
<table> </table> <style> table {overflow-y:scroll;max-height:152px; height:auto;} ...
- C日常语言实践中小(四)——勇者斗恶龙
勇者斗恶龙 愿你的国有n龙的头,你想聘请骑士杀死它(全部的头). 村里有m个骑士能够雇佣,一个能力值为x的骑士能够砍掉恶龙一个致敬不超过x的头,且须要支付x个金币. 怎样雇佣骑士才干砍掉恶龙的全部头, ...
- linux input如何固定设备event handler
于qt开发时间.遇到的问题,usb输入设备(鼠标器,usb 电容屏)在动力分配后自己主动input节点,实例usb鼠标停留电后,分配给自己的主动性/dev/input/event0 mouse0.第一 ...
- 文章13称号 Add Two Numbers
You are given two linked lists representing two non-negative numbers. The digits are stored in rever ...
- Python 摘录LinkedIn用户联系人
CODE: #!/usr/bin/python # -*- coding: utf-8 -*- ''' Created on 2014-8-18 @author: guaguastd @name: l ...
- SPOJ 15. The Shortest Path 堆优化Dijsktra
You are given a list of cities. Each direct connection between two cities has its transportation cos ...
- POJ1149 PIGS 【最大流量】
PIGS Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 16555 Accepted: 7416 Description ...
- android代码签名和混乱的包装
研究了一下android的apk困惑签名和代码包装,假设没有混乱包.然后apk人们可以直接查看源代码反编译出来,尽管混乱包或能看懂.但不是那么容易理解,要求在至少一些时间 假设不混淆,反编译后的代码例 ...
- leaflet开源地图库源码 浏览器&移动设备判断(browser.js)备份
<script> var isIe = !-[1,]; // alert('ie9 之前'+isIe); var ie = 'ActiveXObject' in window; //ale ...
- Android-往来:添加到联系人
//添加到联系人.使用事务 public void testAddContact() { String name[]={"周杰伦","谢霆锋","言承 ...