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

【题解】模板题,见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 ;
}

最新文章

  1. Android--带你一点点封装项目 MVP+BaseActivity+Retrofit+Dagger+RxJava(二)
  2. haslayout详解
  3. JavaScript设计模式——单体模式
  4. iOS,破冰!
  5. ACM题目————字串数
  6. 【BZOJ】【1011】【HNOI2008】遥远的行星
  7. hdu4336 Card Collector 概率dp(或容斥原理?)
  8. [Bhatia.Matrix Analysis.Solutions to Exercises and Problems]ExI.5.10
  9. cocos2d-x实战 C++卷 学习笔记--第4章 win32平台下中文乱码问题
  10. [Javascript] Fetch API
  11. 转:MFC创建多线程实例
  12. 【转】ARM交叉编译工具链
  13. PPT插件 用js制作PPT
  14. JS左侧菜单-03
  15. bzoj2442[Usaco2011 Open]修剪草坪 单调队列优化dp
  16. JAVA多线程学习笔记(1)
  17. Repeater控件的分页实现
  18. Linux共享库 zlog日志
  19. CASpringAnimation的使用
  20. MonoBehaviour.OnValidate

热门文章

  1. 【leetcode】215. Kth Largest Element in an Array
  2. 【BioCode】将多个蛋白质序列分成单个的txt文档
  3. eclipse中jsp页面Invalid location of tag 解决办法分析小结
  4. 【vue】父组件主动调用子组件 /// 非父子组件传值
  5. mybatis(一)MyBatis Generator
  6. 【.Net】在WinForm中选择本地文件
  7. 【BZOJ4945】【NOI2017】游戏(搜索,2-sat)
  8. POJ.3468 A Simple Problem with Integers(线段树 区间更新 区间查询)
  9. MapReduce(三) 典型场景(一)
  10. [杂谈]ACM启程