HYSBZ 1036 【树链剖分】
思路:
裸裸的树链剖分....
树链剖分就是把一棵树分成若干重链和轻链...然后保证形成的线段树上每条链是连续存储的。然后这样就能用线段树进行维护了。
但是每次一定要保证是在同一条链里边....思路就是这样....
感觉最近越来越淡定了,题目卡住了也不怎么着急了,慢慢看代码...嗯...有点像学习的感觉了....
明天青岛理工的邀请赛要好好玩玩...
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int n,m;
int myw[];
bool vis[];
int siz[],dep[],top[],fa[],son[],w[],fp[];
int totw;
char typ[];
long long INF=0x3f3f3f3f3f;
struct edge
{
int id;
edge *next;
};
edge edges[<<];
edge *adj[];
struct tr
{
int s,e,maxx;
long long sum;
};
tr tree[<<];
void build(int k,int s,int e)
{
tree[k].s=s;
tree[k].e=e;
if(s==e)
{
tree[k].sum=tree[k].maxx=myw[fp[s]];
return;
}
int mid=(s+e)>>;
build(k<<,s,mid);
build(k<<|,mid+,e);
tree[k].maxx=max(tree[k<<].maxx,tree[k<<|].maxx);
tree[k].sum=tree[k<<|].sum+tree[k<<].sum;
}
int ednum;
inline void AddEdge(int a,int b)
{
edge *tmp;
tmp=&edges[ednum++];
tmp->id=b;
tmp->next=adj[a];
adj[a]=tmp;
} void dfs1(int id,int mdep,int f)
{
vis[id]=;
dep[id]=mdep;
siz[id]=;
fa[id]=f;
son[id]=;
int tmpsiz=-;
for(edge *it=adj[id]; it; it=it->next)
{
if(!vis[it->id])
{
dfs1(it->id,mdep+,id);
if(tmpsiz<siz[it->id])
{
tmpsiz=siz[it->id];
son[id]=it->id;
}
siz[id]+=siz[it->id];
}
}
}
void dfs2(int id,int ase)
{
vis[id]=;
top[id]=ase;
w[id]=++totw;
fp[totw]=id;
if(son[id])
dfs2(son[id],ase);
for(edge *it=adj[id]; it; it=it->next)
{
if(!vis[it->id])
{
dfs2(it->id,it->id);
}
}
}
long long ans;
void querySum(int k,int s,int e)
{
if(tree[k].e==e&&tree[k].s==s)
{
ans+=tree[k].sum;
return;
}
int mid=(tree[k].s+tree[k].e)>>;
if(e<=mid)
{
querySum(k<<,s,e);
}
else if(s>mid)
{
querySum(k<<|,s,e);
}
else
{
querySum(k<<,s,mid);
querySum(k<<|,mid+,e);
}
}
void qsum(int a,int b)
{
int f1=top[a],f2=top[b]; ans=;
while(f1!=f2)
{
if(dep[f1]<dep[f2])
{
swap(f1,f2);
swap(a,b);
}
querySum(,w[f1],w[a]);
a=fa[f1];
f1=top[a];
}
if(dep[a]>dep[b])
swap(a,b);
querySum(,w[a],w[b]);
printf("%lld\n",ans);
}
void queryMax(int k,int s,int e)
{
if(tree[k].e==e&&tree[k].s==s)
{
ans=max(ans,(long long)tree[k].maxx);
return;
}
int mid=(tree[k].s+tree[k].e)>>;
if(e<=mid)
{
queryMax(k<<,s,e);
}
else if(s>mid)
{
queryMax(k<<|,s,e);
}
else
{
queryMax(k<<,s,mid);
queryMax(k<<|,mid+,e);
}
}
void qmax(int a,int b)
{
int f1=top[a],f2=top[b];
ans=INF*(-);
while(f1!=f2)
{
if(dep[f1]<dep[f2])
{
swap(f1,f2);
swap(a,b);
}
queryMax(,w[f1],w[a]);
a=fa[f1];
f1=top[a];
}
if(dep[a]>dep[b])
swap(a,b);
queryMax(,w[a],w[b]);
printf("%lld\n",ans);
}
void update(int k,int pos,int val)
{
if(tree[k].s==tree[k].e)
{
tree[k].sum=tree[k].maxx=val;
return;
}
int mid=(tree[k].s+tree[k].e)>>;
if(pos<=mid)
update(k<<,pos,val);
else
update(k<<|,pos,val);
tree[k].sum=tree[k<<|].sum+tree[k<<].sum;
tree[k].maxx=max(tree[k<<].maxx,tree[k<<|].maxx);
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
memset(siz,,sizeof(siz));
memset(vis,,sizeof(vis));
memset(son,,sizeof(son));
fa[]=;
totw=;
ednum=;
for(int i=;i<=n;i++)
{
adj[i]=NULL;
}
for(int i=; i<n; i++)
{
int a,b;
scanf("%d%d",&a,&b);
AddEdge(a,b);
AddEdge(b,a);
}
for(int i=; i<=n; i++)
{
scanf("%d",&myw[i]);
}
dfs1(,,);
memset(vis,,sizeof(vis));
dfs2(,);
build(,,totw);
scanf("%d",&m);
for(int i=; i<=m; i++)
{
int a,b;
scanf("%s%d%d",typ,&a,&b);
if(typ[]=='X')
{
qmax(a,b);
}
else if(typ[]=='M')
{
qsum(a,b);
}
else if((typ[]=='N'))
{
update(,w[a],b);
}
}
}
}
/*
8
1 2
1 4
2 3
3 8
5 6
7 5
2 5
3 7 6 5 8 2 1 0
1000
*/
HYSBZ 1036 【树链剖分】的更多相关文章
- HYSBZ 1036树链剖分
一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从 ...
- HDU 3966 & POJ 3237 & HYSBZ 2243 树链剖分
树链剖分是一个很固定的套路 一般用来解决树上两点之间的路径更改与查询 思想是将一棵树分成不想交的几条链 并且由于dfs的顺序性 给每条链上的点或边标的号必定是连着的 那么每两个点之间的路径都可以拆成几 ...
- BZOJ 1036 && 树链剖分
还是太弱啊..各种数据结构只听过名字却没有一点概念..树链剖分也在这个范畴..今天来进一步深化一下教育改革推进全民素质提高. 性质 忘了在哪里看到的一篇blog有一句话讲得非常好,树链剖分不是一种数据 ...
- HYSBZ - 2243 树链剖分 + 线段树 处理树上颜色段数
用线段树处理颜色段数 记录区间内的颜色段数,区间右端点的颜色,区间右端点的颜色. int tr[maxn<<2], lc[maxn<<2], rc[maxn<<2] ...
- BZOJ 1036 [ZJOI2008]树的统计Count (树链剖分 - 点权剖分 - 单点权修改)
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1036 树链剖分模版题,打的时候注意点就行.做这题的时候,真的傻了,单词拼错检查了一个多小时 ...
- Luogu 2590 [ZJOI2008]树的统计 / HYSBZ 1036 [ZJOI2008]树的统计Count (树链剖分,LCA,线段树)
Luogu 2590 [ZJOI2008]树的统计 / HYSBZ 1036 [ZJOI2008]树的统计Count (树链剖分,LCA,线段树) Description 一棵树上有n个节点,编号分别 ...
- HYSBZ 1036(树链剖分)
题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=28982#problem/E 题意:给定一棵树及树上的点权,要求三种操作: 1) ...
- HYSBZ 1036 树的统计Count(树链剖分)题解
思路: 树链剖分,不知道说什么...我连模板都不会用 代码: #include<map> #include<ctime> #include<cmath> #incl ...
- BZOJ 1036: [ZJOI2008]树的统计Count [树链剖分]【学习笔记】
1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 14302 Solved: 5779[Submit ...
随机推荐
- oracle中where 子句和having子句中的区别
1.where 不能放在GROUP BY 后面 2.HAVING 是跟GROUP BY 连在一起用的,放在GROUP BY 后面,此时的作用相当于WHERE 3.WHERE 后面的条件中不能有聚集函数 ...
- [Hibernate] - Annotations
Hibernate使用Annotations最简单例子: hibernate.cfg.xml <?xml version="1.0" encoding="UTF-8 ...
- cmd命令运行php,php通过cmd运行文件
一.cmd命令运行php 1.通过配置环境变量 >php "php文件" 如果要待参数 php -q "php文件" 参数 php获取参数 $a = $a ...
- java 反射机制01
// */ // ]]> java反射机制01 Table of Contents 1 反射机制 2 反射成员 2.1 java.lang.Class 2.2 Constructor 2.3 ...
- c#.net 访问SQL SERVER 时提示:尝试读取或写入受保护的内存。这通常指示其他内存已损坏
解决方法: 管理员身份运行 cmd -> 输入 netsh winsock reset 然后重启电脑. 引用 :http://blog.csdn.net/laijieyao/article/d ...
- IntelliJ IDEA中如何设置同时打开多个文件且分行显示?
Window→Editor Tabs→Tabs Placement→Show Tabs in Single Row 取消选中后即可在多行显示 下图为实际显示效果: 还可以自行设置打开文件窗口数(默认 ...
- Linux下nice/renice命令小结
1. nice命令 内核根据进程的nice值决定进程需要多少处理器时间. nice值的取值范围是是: -20到20. 一个具有-20 的 nice 值的进程有很高的优先级. 一个 nice 值为 20 ...
- [git]Git常用命令
转自:http://www.cnblogs.com/idche/archive/2011/07/05/2098165.htmlGIT 学习笔记 集中化的版本控制系统 CVCS(Centralized ...
- SecureCRT上传、下载文件 使用sz与rz命令
首先安装:apt-get install lrzsz SecureCRT这款SSH客户端软件同时具备了终端仿真器和文件传输功能.比ftp命令方便多了,而且服务器不用再开FTP服务了.rz,sz是便是L ...
- TortoiseSVN 同步分支
对比工具可以使用 winmerge 和 beyond compare ,winmerge免费小巧,beyond compare功能更强大.这两款工具都比TortoiseSVN自带的对比工具要好一些. ...