HDU 5044 Tree --树链剖分
题意:给一棵树,两种操作: ADD1: 给u-v路径上所有点加上值k, ADD2:给u-v路径上所有边加上k,初始值都为0,问最后每个点和每条边的值,输出。
解法:树链剖分可做,剖出来如果直接用线段树来区间更新的话会TLE,所以要换一种姿势,有一种树链剖分的经典姿势就是看做树状数组一样,每次加值的时候,比如u->v之间加一个值k,那么在u处+k,v+1处-k即可,然后扫一遍,每次把当前位置要做的操作做完,此时总共加的值就是当前处的值,扫一遍的时候维护的是前缀的和,也就是两个ans不清零。
这题卡时间太紧,不加读入挂会T,不加输出挂的话跑4921ms,也是飘过,加了输入输出挂才稍微好点,4687ms,可能是树链剖分不够优越
代码:
#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#define lll __int64
using namespace std;
#define N 100007 int siz[N]; //子树大小
int son[N]; //重儿子
int dep[N]; //深度
int pos[N],apos[N]; //点在线段树中的位置
int Top[N]; //所在重链的祖先
int fa[N]; //父节点
lll eans[N],nans[N]; //答案
int head[*N],tot,POS,n,m;
struct Edge
{
int v,next;
}G[*N],Qe[*N],Qn[*N];
int heade[*N],headn[*N],tote,totn;
struct node
{
int u,v;
}edge[N]; void init()
{
POS = tot = tote = totn = ;
memset(head,-,sizeof(head));
memset(son,-,sizeof(son));
memset(heade,-,sizeof(heade));
memset(headn,-,sizeof(headn));
} void addedge(int u,int v)
{
G[tot].v = v, G[tot].next = head[u], head[u] = tot++;
G[tot].v = u, G[tot].next = head[v], head[v] = tot++;
} void ADDNedge(int u,int v) //代替vector来存操作
{
Qn[totn].v = v, Qn[totn].next = headn[u], headn[u] = totn++;
} void ADDEedge(int u,int v) //代替vector来存操作
{
Qe[tote].v = v, Qe[tote].next = heade[u], heade[u] = tote++;
} void dfs(int u,int f)
{
dep[u] = dep[f]+;
siz[u] = ;
for(int i=head[u];i!=-;i=G[i].next)
{
int v = G[i].v;
if(v == f) continue;
fa[v] = u;
dfs(v,u);
if(son[u] == - || siz[v] > siz[son[u]]) son[u] = v;
siz[u] += siz[v];
}
} void dfs2(int u,int top)
{
pos[u] = ++POS;
apos[POS] = u;
Top[u] = top;
if(son[u] != -) dfs2(son[u],top);
for(int i=head[u];i!=-;i=G[i].next)
{
int v = G[i].v;
if(v != fa[u] && v != son[u])
dfs2(v,v);
}
} void AddEdge(int u,int v,int k)
{
int fx = Top[u], fy = Top[v];
while(fx != fy)
{
if(dep[fx] < dep[fy])
{
swap(u,v);
swap(fx,fy);
}
ADDEedge(pos[fx],k);
ADDEedge(pos[u]+,-k);
u = fa[fx];
fx = Top[u];
}
if(dep[u] > dep[v]) swap(u,v);
ADDEedge(pos[son[u]],k);
ADDEedge(pos[v]+,-k);
} void AddNode(int u,int v,int k)
{
int fx = Top[u], fy = Top[v];
while(fx != fy)
{
if(dep[fx] < dep[fy])
{
swap(u,v);
swap(fx,fy);
}
ADDNedge(pos[fx],k);
ADDNedge(pos[u]+,-k);
u = fa[fx];
fx = Top[u];
}
if(dep[u] > dep[v]) swap(u,v);
ADDNedge(pos[u],k);
ADDNedge(pos[v]+,-k);
} inline int in()
{
char ch;
int a = ;
while((ch = getchar()) == ' ' || ch == '\n');
a += ch - '';
while((ch = getchar()) != ' ' && ch != '\n')
{
a *= ;
a += ch - '';
}
return a;
} inline void out(lll num){
bool flag=false;
if(num<){
putchar('-');
num=-num;
}
int ans[],top=;
while(num!=){
ans[top++]=num%;
num/=;
}
if(top==)
putchar('');
for(int i=top-;i>=;i--){
char ch=ans[i]+'';
putchar(ch);
}
} int main()
{
int u,v,k,i,j,t,cs = ;
char ss[];
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
init();
for(i=;i<n;i++)
{
edge[i].u = in();
edge[i].v = in();
addedge(edge[i].u,edge[i].v);
}
dep[] = ;
dfs(,);
dfs2(,);
while(m--)
{
scanf("%s",ss);
u = in(), v = in(), k = in();
if(ss[] == '') //node
AddNode(u,v,k);
else
AddEdge(u,v,k);
}
printf("Case #%d:\n",cs++);
lll ansedge = ,ansnode = ;
for(i=;i<=n;i++)
{
for(j=headn[i];j!=-;j=Qn[j].next)
ansnode += Qn[j].v;
for(j=heade[i];j!=-;j=Qe[j].next)
ansedge += Qe[j].v;
nans[apos[i]] = ansnode;
eans[apos[i]] = ansedge;
}
for(i=;i<=n;i++)
{
out(nans[i]);
printf("%c",i==n?'\n':' ');
}
for(i=;i<n;i++)
{
int u = edge[i].u, v = edge[i].v;
if(dep[u] > dep[v]) swap(u,v);
out(eans[v]);
printf("%c",i==n-?'\n':' ');
}
if(n == ) puts(""); //PE..
}
return ;
}
HDU 5044 Tree --树链剖分的更多相关文章
- HDU 5044 Tree 树链剖分+区间标记
Tree Problem Description You are given a tree (an acyclic undirected connected graph) with N nodes. ...
- HDU 5044 (树链剖分+树状数组+点/边改查)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5044 题目大意:修改链上点,修改链上的边.查询所有点,查询所有边. 解题思路: 2014上海网赛的变 ...
- Hdu 5274 Dylans loves tree (树链剖分模板)
Hdu 5274 Dylans loves tree (树链剖分模板) 题目传送门 #include <queue> #include <cmath> #include < ...
- hdu 5458 Stability(树链剖分+并查集)
Stability Time Limit: 3000/2000 MS (Java/Others) Memory Limit: 65535/102400 K (Java/Others)Total ...
- POJ3237 Tree 树链剖分 边权
POJ3237 Tree 树链剖分 边权 传送门:http://poj.org/problem?id=3237 题意: n个点的,n-1条边 修改单边边权 将a->b的边权取反 查询a-> ...
- HDU 5614 Baby Ming and Matrix tree 树链剖分
题意: 给出一棵树,每个顶点上有个\(2 \times 2\)的矩阵,矩阵有两种操作: 顺时针旋转90°,花费是2 将一种矩阵替换为另一种矩阵,花费是10 树上有一种操作,将一条路经上的所有矩阵都变为 ...
- Tree HDU - 6547 (树链剖分,线段树)
wls 有三棵树,树上每个节点都有一个值 ai,现在有 2 种操作: 将一条链上的所有节点的值开根号向下取整: 求一条链上值的和: 链的定义是两点之间的最短路. Input 第一行两个数 n, q 分 ...
- 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][ ...
随机推荐
- ahjesus fstab修改错误了如何修复
fstab修改错误了如何修复 当你不小心把磁盘表输入错误以后,系统总是让你按ctrl+D重新启动或者输入密 码进入shell,你输入密码登陆后, 编辑文件是只读的,执行下面的命令后就可以编辑了 ...
- zeromq 学习和python实战
参考文档: 官网 http://zeromq.org/ http://www.cnblogs.com/rainbowzc/p/3357594.html 原理解读 zeromq只是一层针对socke ...
- android.widget.RadioButton 单选按钮(转)
大家好,我们今天这一节要介绍的是RadioGroup 的组事件.RadioGroup 可将各自不同的RadioButton ,设限于同一个Radio 按钮组,同一个RadioGroup 组里的按钮,只 ...
- JS基本概念 -- 数据类型(一)
ECMAScript中有5种简单数据类型(也成为基本数据类型): Undefined.Null.Boolean.Number.String; 1种复杂数据类型: Object,Object本质上是由一 ...
- storm学习途径
作者: xumingming | 网址: http://xumingming.sinaapp.com/category/storm/ 作者:量子恒道 | 网址:http://blog.linezin ...
- Unable to start activity ComponentInfo{com.first/com.first.Game}
原因一: xxx的错误,若为R.layout.main 那么应该是main.xml文件中的标签 使用错误,最常见的而且编译器不会提示的错误就是 android:name 和android:id 两者 ...
- JavaWeb开发必过关-Servlet学习(一)
一.什么是Servlet servlet其实是一个小程序,它是运行在服务器上的,一个servlet就是一个Java类,可以通过"请求-响应"编程模型来访问这个驻留在服务器内存的Se ...
- MongoDB 初识1: 启动MongoDB
Mongodb可作为网络服务器运行,客户端可连接到该服务器并执行操作. 1. 首先,用户必须下载Mongodb并解压,运行mongod命令启动实例 下载地址:http://www.mongodb.or ...
- JS 日期对象在浏览器间的若干差异
JS中 ,通过 new Date() 可以获取当前时间 也可以通过 new Date("2013/12/12 8:00:00")的方式,创建某个指定时间对象 在Chrome和FF下 ...
- Mysql的float类型造成的困扰总结
因为换了工作正在学习使用MySQL,今天领导提出了一个问题,如下: X列是累加值,A列是每日新增值,那么X2应该是X1+A2,而且存储过程里也是这样计算的.可是奇怪的是X2的值却总是和正确值(2396 ...