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 ...
随机推荐
- 【转】.NET多种WebKit内核/Blink内核浏览器初步测评报告
第1篇:.NET多种WebKit内核/Blink内核浏览器初步测评报告 本文转自“吾乐吧软件站”,原文链接:http://www.wuleba.com/?p=23590 报告研究时间:2013-10- ...
- SqlServer数据库正在还原的解决办法
1)管理器不会主动刷新,需要手工刷新一下才能看到最新状态(性能方面的考虑) 2)很少情况下,恢复进程被挂起了.这个时候假设你要恢复并且回到可访问状态,要执行: RESTORE database ...
- Tortoisesvn单个文件夹checkout
- C#子线程刷新界面并关闭窗体
目的:要循环刷新界面上的控件,同时不影响用户操作.循环结束后关闭窗体. 步骤:先创建一个窗体,窗体中拖入一个lable控件(label1),一个button控件(button1) 代码窗口输入: // ...
- Android中Service的使用详解和注意点(LocalService)
Android中Service的使用详解和注意点(LocalService) 原文地址 开始,先稍稍讲一点android中Service的概念和用途吧~ Service分为本地服务(LocalServ ...
- JS request函数 用来获取url参数
function request(strParame) { var args = new Object( ); var query = location.search.substring(1); va ...
- POJ #2479 - Maximum sum
Hi, I'm back. This is a realy classic DP problem to code. 1. You have to be crystal clear about what ...
- linux下查看进程运行的时间
原文链接:http://www.centoscn.com/CentOS/2014/0403/2724.html 可通过ps 来查看,通过参数 -o 来查看 例: ps -eo pid,tty,user ...
- for name in loop Shell
for NAME in joe jane juliedoADDRESS="$NAME@example.com"MESSAGE='Projects are due today!'ec ...
- python学习-day01
一.python介绍: python是一种面向对象的解释型计算机程序设计语言,由荷兰人Guido van Rossum于1989年发明,第一个公开发行版发行于1991年. Python语法简洁清晰,特 ...