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 ...
随机推荐
- samba 服务
samba-client-3.6.9-167.el6_5.i686 samba-3.6.9-167.el6_5.i686 samba-common-3.6.9-167.el6_5.i686 samba ...
- JavaScript对象就是一组属性(方法)的集合
在JavaScript中,每个对象可以看作是多个属性(方法)的集合,引用一个属性(方法) 很简单,即: 对象名.属性(方法)名 除此之外,还可以用方括号的形式来引用: 对象名[“属性(方法)名”] 注 ...
- Tkinter单选框及滚动条
界面:左侧是单选框,右侧是信息显示框,下方是按扭 功能:点击开始爬取按扭,则会自动执行函数,显示在文本框中 indicatoron = 0 改变单选框按扭样式 效果图一: 效果图二: 效果图三: 示例 ...
- MySQL分库分表环境下全局ID生成方案 转
在大型互联网应用中,随着用户数的增加,为了提高应用的性能,我们经常需要对数据库进行分库分表操作.在单表时代,我们可以完全依赖于数据库的自增ID来唯一标识一个用户或数据对象.但是当我们对数据库进行了分库 ...
- 解决“未启用当前数据库的 SQL Server Service Broker,因此查询通知不受支持。如果希望使用通知,请为此数据库启用 Service Broker”错误
转自:http://blog.csdn.net/andrew_wx/article/details/6947317 解决办法: ALTER DATABASE 数据库名称 SET NEW_BROKER ...
- 使用UpdatePanel 页面脚本不起作用
在后台中这样注册js方法 ScriptManager.RegisterStartupScript(this.Page, this.Page.GetType(), "", " ...
- 屏幕取色工具推荐 ColorPix
很好用的一个屏幕取色工具,方便套页面时,在图片上取色. 用鼠标指到取色未知,按CTRL+C,就可复制16进制的颜色值. 下载地址:http://files.cnblogs.com/zjfree/Col ...
- Javascript中函数的四种调用方式
一.Javascript中函数的几个基本知识点: 1.函数的名字只是一个指向函数的指针,所以即使在不同的执行环境,即不同对象调用这个函数,这个函数指向的仍然是同一个函数. 2.函数中有两个特殊的内部属 ...
- 重复ID的记录,只显示其中1条
--重复ID的记录,只显示其中1条 --生成原始表 select * into #tempTable from ( select '1' as id ,'a' as name union all se ...
- AP_应付税务预扣税Withholding Tax的设定和使用(案例)
2014-07-13 Created By BaoXinjian