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

【题解】模板题,见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. CCF——数列分段201509-1

    问题描述 给定一个整数数列,数列中连续相同的最长整数序列算成一段,问数列中共有多少段? 输入格式 输入的第一行包含一个整数n,表示数列中整数的个数. 第二行包含n个整数a1, a2, …, an,表示 ...

  2. 让VS2013支持 C# 6.0 语法

    还未升级使用VS2015前,又想尝试使用C# 6.0的语言特性,可以用以下方法启用: VS2013中“工具”下选择“程序包管理器控制台”: 选中需要使用C# 6.0的项目,再敲入"Insta ...

  3. Java 中 Vector、ArrayList、List 使用深入剖析

    线性表,链表,哈希表是常用的数据结构,在进行Java开发时,JDK已经为我们提供了一系列相应的类来实现基本的数据结构.这些类均在java.util包中.本文试图通过简单的描述,向读者阐述各个类的作用以 ...

  4. App流量测试--使用安卓自身提供的TCP收发长度统计功能

    在Linux系统有3个地方保存流量统计文件,对于Android系统同样也适用: (1)在/proc/net/dev下可以查看各个网络接口的收发流量  (等同adb shell cat /proc/pi ...

  5. idea Class<>表示的含义

  6. java 常量 jvm在编译期能确定常量的 所以相等 但不能确定变量的范围 所以变量相加会产生新的

  7. Python中int()函数的用法浅析

      int()是Python的一个内部函数 Python系统帮助里面是这么说的 >>> help(int)  Help on class int in module __builti ...

  8. 高rong效chang的可持久化treap

    很多人觉得可持久化treap很慢,但是事实上只是他们可持久化treap的写法不对.他们一般是用split和merge实现所有功能,但是这样会有许多不必要的分裂.其实我们可以用一种特殊的方式来实现插入和 ...

  9. Django之CSS,JS静态文件的配置

    一. 专门创建一个目录放静态文件,即CSS,JS等. 1)先把jquery.min拿过来. 2)新建一个CSS文件放入样式 3)在login.html中引入.css文件 在login.html中引入. ...

  10. Fdisk 分区详解

    Fdisk 分区详解 来源 http://blog.itpub.net/20674423/viewspace-722812/ 1.             通过Fdisk查看系统分区详细信息: Fdi ...