【算法】树链剖分+线段树

【题解】模板题,见http://www.cnblogs.com/onioncyc/p/6207462.html

调用线段数时要用新编号pos[i] !!!

#include<cstdio>
#include<cctype>
#include<algorithm>
using namespace std;
const int maxn=,inf=0x3f3f3f3f;
int pos[maxn],top[maxn],dfsnum,f[maxn],deep[maxn],size[maxn],first[maxn],n,tot,a[maxn];
struct edge{int u,v,from;}e[maxn*];
struct tree{int l,r,sum,mx;}t[maxn*];
int read()
{
char c;int s=,t=;
while(!isdigit(c=getchar()))if(c=='-')t=-;
do{s=s*+c-'';}while(isdigit(c=getchar()));
return s*t;
}
void insert(int u,int v)
{tot++;e[tot].u=u;e[tot].v=v;e[tot].from=first[u];first[u]=tot;}
void dfs1(int x,int fa)
{
size[x]=;
for(int i=first[x];i;i=e[i].from)
if(e[i].v!=fa)
{
int y=e[i].v;
deep[y]=deep[x]+;
f[y]=x;
dfs1(y,x);
size[x]+=size[y];
}
}
void dfs2(int x,int tp,int fa)
{
int k=;
pos[x]=++dfsnum;
top[x]=tp;
for(int i=first[x];i;i=e[i].from)
if(e[i].v!=fa&&size[e[i].v]>size[k])k=e[i].v;
if(k==)return;
dfs2(k,tp,x);
for(int i=first[x];i;i=e[i].from)
if(e[i].v!=fa&&e[i].v!=k)dfs2(e[i].v,e[i].v,x);
}
void build(int k,int l,int r)
{
t[k].l=l;t[k].r=r;
if(l!=r)
{
int mid=(l+r)>>;
build(k<<,l,mid);
build(k<<|,mid+,r);
}
}
void change(int k,int x,int y)
{
int left=t[k].l,right=t[k].r;
if(left==right){t[k].mx=y;t[k].sum=y;}
else
{
int mid=(left+right)>>;
if(x<=mid)change(k<<,x,y);
else change(k<<|,x,y);
t[k].sum=t[k<<].sum+t[k<<|].sum;
t[k].mx=max(t[k<<].mx,t[k<<|].mx);
}
}
int ask_mx(int k,int l,int r)
{
int left=t[k].l,right=t[k].r;
if(l<=left&&right<=r)return t[k].mx;
else
{
int mid=(left+right)>>,maxs=-inf;
if(l<=mid)maxs=ask_mx(k<<,l,r);
if(r>mid)maxs=max(maxs,ask_mx(k<<|,l,r));
return maxs;
}
}
int ask_sum(int k,int l,int r)
{
int left=t[k].l,right=t[k].r;
if(l<=left&&right<=r)return t[k].sum;
else
{
int mid=(left+right)>>,sums=;
if(l<=mid)sums=ask_sum(k<<,l,r);
if(r>mid)sums+=ask_sum(k<<|,l,r);
return sums;
}
}
int solve_mx(int x,int y)
{
int maxs=-inf;
while(top[x]!=top[y])
{
if(deep[top[x]]<deep[top[y]])swap(x,y);
maxs=max(maxs,ask_mx(,pos[top[x]],pos[x]));
x=f[top[x]];
}
if(pos[x]>pos[y])swap(x,y);
maxs=max(maxs,ask_mx(,pos[x],pos[y]));
return maxs;
}
int solve_sum(int x,int y)
{
int sums=;
while(top[x]!=top[y])
{
if(deep[top[x]]<deep[top[y]])swap(x,y);
sums+=ask_sum(,pos[top[x]],pos[x]);
x=f[top[x]];
}
if(pos[x]>pos[y])swap(x,y);
sums+=ask_sum(,pos[x],pos[y]);
return sums;
}
int main()
{
n=read();
for(int i=;i<n;i++)
{
int u=read(),v=read();
insert(u,v);
insert(v,u);
}
for(int i=;i<=n;i++)a[i]=read();
dfs1(,-);
dfs2(,,-);
build(,,n);
for(int i=;i<=n;i++)change(,pos[i],a[i]);
int Q=read();char ch[];
for(int i=;i<=Q;i++)
{
scanf("%s",ch);
int u=read(),v=read();
if(ch[]=='H')change(,pos[u],v);//QAQ 调用线段树必须用新编号,下面用旧编号是因为子程序中用了新编号T_T
if(ch[]=='M')printf("%d\n",solve_mx(u,v));
if(ch[]=='S')printf("%d\n",solve_sum(u,v));
}
return ;
}

【BZOJ】1036 [ZJOI2008]树的统计Count的更多相关文章

  1. BZOJ.1036 [ZJOI2008]树的统计Count ( 点权树链剖分 线段树维护和与最值)

    BZOJ.1036 [ZJOI2008]树的统计Count (树链剖分 线段树维护和与最值) 题意分析 (题目图片来自于 这里) 第一道树链剖分的题目,谈一下自己的理解. 树链剖分能解决的问题是,题目 ...

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

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

  3. BZOJ 1036: [ZJOI2008]树的统计Count

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 14354  Solved: 5802 [Subm ...

  4. bzoj 1036 [ZJOI2008]树的统计Count(树链剖分,线段树)

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

  5. Bzoj 1036: [ZJOI2008]树的统计Count 树链剖分,LCT

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

  6. 数据结构(LCT动态树):BZOJ 1036: [ZJOI2008]树的统计Count

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

  7. BZOJ 1036: [ZJOI2008]树的统计Count( 树链剖分 )

    树链剖分... 不知道为什么跑这么慢 = = 调了一节课啊跪.. ------------------------------------------------------------------- ...

  8. bzoj 1036: [ZJOI2008]树的统计Count 树链剖分+线段树

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

  9. bzoj 1036: [ZJOI2008]树的统计Count (树链剖分+线段树 点权)

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

  10. BZOJ 1036: [ZJOI2008]树的统计Count (树链剖分模板题)

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

随机推荐

  1. android入门 — Activity生命周期

    Activity总共有7个回调方法,代表着不同的生命周期的环节. 1.onCreate() 在活动第一次被创建的时候调用.在这个方法中需要完成活动的初始化操作,比如说加载布局.绑定事件等. 2.onS ...

  2. C++ Primer Plus学习:第六章

    C++入门第六章:分支语句和逻辑运算符 if语句 语法: if (test-condition) statement if else语句 if (test-condition) statement1 ...

  3. git因commit的记录太大导致push失败解决方法

    发现好像这个方法不好使.......~~!还是会失败 如果有人或者自己失误把不该同步的大文件如数据或日志或其他中间文件给commit了并且push了,然后你删掉了,但是其实他仍然在你的git记录中,你 ...

  4. laravel 字段映射问题,表单中提交字段与数据表中字段不一致

    在遇到提交表单时,表单中的name属性与数据表中的字段不一致,报错, 解决方法: 参考1:提交表单的时候,表单的name属性和数据表字段名称是一样的,这样有什么不妥么? 你数据库的信息给前端透露得越多 ...

  5. PHP中类中成员及常量

    类中成员概述 面向对象编程,是需要通过“对象”去做什么事情(以完成某种任务): 而: 对象总是来源于类: 所以: 面向对象的编程,一切都是从定义类开始: 类中成员分为3大类: 属性: 方法: 常量: ...

  6. java 使用volatile实现线程数据的共享

    java 使用volatile实现线程数据的共享 直接上代码看效果: public class VolatileTest extends Thread { private volatile boole ...

  7. 【bzoj2669】[cqoi2012]局部极小值 容斥原理+状压dp

    题目描述 有一个n行m列的整数矩阵,其中1到nm之间的每个整数恰好出现一次.如果一个格子比所有相邻格子(相邻是指有公共边或公共顶点)都小,我们说这个格子是局部极小值. 给出所有局部极小值的位置,你的任 ...

  8. Command Network OpenJ_Bailian - 3436(最小有向生成树模板题)

    链接: http://poj.org/problem?id=3164 题目: Command Network Time Limit: 1000MS   Memory Limit: 131072K To ...

  9. word2013 如何套用模版

    文件-->选项-->加载项-->最下面下拉框选择“模版”-->点击转到

  10. 【刷题】BZOJ 3365 [Usaco2004 Feb]Distance Statistics 路程统计

    Description 在得知了自己农场的完整地图后(地图形式如前三题所述),约翰又有了新的问题.他提供 一个整数K(1≤K≤109),希望你输出有多少对农场之间的距离是不超过K的. Input 第1 ...