思路:

裸裸的树链剖分....

树链剖分就是把一棵树分成若干重链和轻链...然后保证形成的线段树上每条链是连续存储的。然后这样就能用线段树进行维护了。

但是每次一定要保证是在同一条链里边....思路就是这样....

感觉最近越来越淡定了,题目卡住了也不怎么着急了,慢慢看代码...嗯...有点像学习的感觉了....

明天青岛理工的邀请赛要好好玩玩...

#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 【树链剖分】的更多相关文章

  1. HYSBZ 1036树链剖分

    一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从 ...

  2. HDU 3966 & POJ 3237 & HYSBZ 2243 树链剖分

    树链剖分是一个很固定的套路 一般用来解决树上两点之间的路径更改与查询 思想是将一棵树分成不想交的几条链 并且由于dfs的顺序性 给每条链上的点或边标的号必定是连着的 那么每两个点之间的路径都可以拆成几 ...

  3. BZOJ 1036 && 树链剖分

    还是太弱啊..各种数据结构只听过名字却没有一点概念..树链剖分也在这个范畴..今天来进一步深化一下教育改革推进全民素质提高. 性质 忘了在哪里看到的一篇blog有一句话讲得非常好,树链剖分不是一种数据 ...

  4. HYSBZ - 2243 树链剖分 + 线段树 处理树上颜色段数

    用线段树处理颜色段数 记录区间内的颜色段数,区间右端点的颜色,区间右端点的颜色. int tr[maxn<<2], lc[maxn<<2], rc[maxn<<2] ...

  5. BZOJ 1036 [ZJOI2008]树的统计Count (树链剖分 - 点权剖分 - 单点权修改)

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1036 树链剖分模版题,打的时候注意点就行.做这题的时候,真的傻了,单词拼错检查了一个多小时 ...

  6. Luogu 2590 [ZJOI2008]树的统计 / HYSBZ 1036 [ZJOI2008]树的统计Count (树链剖分,LCA,线段树)

    Luogu 2590 [ZJOI2008]树的统计 / HYSBZ 1036 [ZJOI2008]树的统计Count (树链剖分,LCA,线段树) Description 一棵树上有n个节点,编号分别 ...

  7. HYSBZ 1036(树链剖分)

    题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=28982#problem/E 题意:给定一棵树及树上的点权,要求三种操作: 1) ...

  8. HYSBZ 1036 树的统计Count(树链剖分)题解

    思路: 树链剖分,不知道说什么...我连模板都不会用 代码: #include<map> #include<ctime> #include<cmath> #incl ...

  9. BZOJ 1036: [ZJOI2008]树的统计Count [树链剖分]【学习笔记】

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 14302  Solved: 5779[Submit ...

随机推荐

  1. 运行setup.js文件

    C:\Windows\System32>wscript.exe setup.js

  2. DebugDiag收集Dump的使用说明

    DebugDiag简介 Debug Diagnostic Tool (DebugDiag)是微软提供的工具,可以用来追踪windows平台下的程序崩溃,卡死,内存泄漏等一些疑难问题的原因,按照问题类别 ...

  3. 你了解System.out.println()的真正含义吗?

    在Java编程中,我们常常用 System.out.println(); 来输出字符串,也许我们都已经猜到println()是方法名,但System是什么,out又是什么呢? 其实System是jav ...

  4. ORALCE 游标简单的实例

    --取简单的游标 declare cursor sp is select * from user_tables; myrecord user_tables%ROWTYPE; begin open sp ...

  5. (zt)Lua的多任务机制——协程(coroutine)

    原帖:http://blog.csdn.net/soloist/article/details/329381 并发是现实世界的本质特征,而聪明的计算机科学家用来模拟并发的技术手段便是多任务机制.大致上 ...

  6. [转]Python中urllib与urllib2的区别与联系

    引用文章1:http://my.oschina.net/u/558071/blog/144792 引用文章2:http://zhuoqiang.me/python-urllib2-usage.html ...

  7. Hibernate3回顾-6-hibernate缓存(性能优化策略)

    主要来源: http://blog.csdn.net/csh624366188/article/details/7612142  (比较详细) http://www.cnblogs.com/20091 ...

  8. linux 解压,源码包

    从网络上下载到的源码包, 最常见的是 .tar.gz 包, 还有一部分是 .tar.bz2包   要解压很简单 :   .tar.gz     格式解压为          tar   -zxvf   ...

  9. HackerRank "Poisonous Plants"

    I had the same BFS idea as one of the AC code this: because dying pattern is spead from the initial ...

  10. ASP.NET动态加载Js代码到Head标签中(三种方法)

    方法一代码如下: HtmlGenericControl Include2 = new HtmlGenericControl("script"); Include2.Attribut ...