1036: [ZJOI2008]树的统计Count

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 15120  Solved: 6141
[Submit][Status][Discuss]

Description

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

Input

  输入的第一行为一个整数n,表示节点的个数。接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有
一条边相连。接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。接下来1行,为一个整数q,表示操作
的总数。接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。 
对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。

Output

  对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。

Sample Input

4
1 2
2 3
4 1
4 2 1 3
12
QMAX 3 4
QMAX 3 3
QMAX 3 2
QMAX 2 3
QSUM 3 4
QSUM 2 1
CHANGE 1 5
QMAX 3 4
CHANGE 3 6
QMAX 3 4
QMAX 2 4
QSUM 3 4

Sample Output

4
1
2
2
10
6
5
6
5
16

HINT

//树链剖分模板 我是个安静的初学者
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 300001 using namespace std;
int pos[maxn],son[maxn],top[maxn],size[maxn];
int deep[maxn],fa[maxn],head[maxn],a[maxn];
int tot,n,m,cnt,maxsize,x,y,num;
struct node{int l,r,sum,max;}tre[maxn<<];
struct edge{int to,pre;}e[maxn<<]; int read()
{
int x=,f=;char c=getchar();
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
} void add(int from,int to)
{
e[++num].to=to;
e[num].pre=head[from];
head[from]=num;
} void build(int now,int l,int r)
{
tre[now].l=l;tre[now].r=r;
if(l==r)
{
tre[now].sum=tre[now].max=;
return;
}
int mid=(l+r)>>;
build(now<<,l,mid);build(now<<|,mid+,r);
tre[now].sum=tre[now<<].sum+tre[now<<|].sum;
tre[now].max=max(tre[now<<].max,tre[now<<|].max);
} void dfs1(int u)
{
size[u]=;//初始化儿子个数
for(int i=head[u];i;i=e[i].pre)
{
int v=e[i].to;
if(fa[u]==v) continue;
deep[v]=deep[u]+;//更新深度
fa[v]=u;//更新父亲节点
dfs1(v);size[u]+=size[v];//更新儿子个数
}
return;
} void dfs2(int u,int Top)
{
int k=;maxsize++;//节点总数
pos[u]=maxsize;top[u]=Top;//节点编号;属于哪一条链;
for(int i=head[u];i;i=e[i].pre)
{
int v=e[i].to;
if(deep[v]>deep[u]&&size[v]>size[k]) k=v;//找重儿子
}
if(!k) return;//当前点就是
dfs2(k,Top);//处理当前点
for(int i=head[u];i;i=e[i].pre)
if(deep[e[i].to]>deep[u]&&e[i].to!=k) dfs2(e[i].to,e[i].to);//新的一条链
return;
} void insert(int now,int x,int val)//插点
{
if(tre[now].l==tre[now].r)
{
tre[now].sum=tre[now].max=val;
return;
}
int mid=(tre[now].l+tre[now].r)>>;
if(x<=mid) insert(now<<,x,val);
else if(x>mid) insert(now<<|,x,val);
tre[now].sum=tre[now<<].sum+tre[now<<|].sum;
tre[now].max=max(tre[now<<].max,tre[now<<|].max);
} int querysum(int k,int l,int r)
{
if(l<=tre[k].l&&tre[k].r<=r) return tre[k].sum;
int mid=(tre[k].l+tre[k].r)>>,total=;
if(l<=mid) total+=querysum(k<<,l,r);
if(r>mid) total+=querysum(k<<|,l,r);
return total;
} int querymax(int k,int l,int r)
{
if(l<=tre[k].l&&tre[k].r<=r) return tre[k].max;
int mid=(tre[k].l+tre[k].r)>>,total=-1e9;
if(l<=mid) total=max(total,querymax(k<<,l,r));
if(r>mid) total=max(total,querymax(k<<|,l,r));
return total;
} int solvesum(int x,int y)
{
int ans=;
while(top[x]!=top[y])//找同一条链
{
if(deep[top[x]]<deep[top[y]]) swap(x,y);//深的才能往上跳
ans+=querysum(,pos[top[x]],pos[x]);
x=fa[top[x]];//往上跳
}
if(pos[x]>pos[y])swap(x,y);//来到了一条链上
ans+=querysum(,pos[x],pos[y]);
return ans;
} int solvemax(int x,int y)
{
int ans=-1e9;
while(top[x]!=top[y])
{
if(deep[top[x]]<deep[top[y]]) swap(x,y);
ans=max(ans,querymax(,pos[top[x]],pos[x]));
x=fa[top[x]];
}
if(pos[x]>pos[y]) swap(x,y);
ans=max(ans,querymax(,pos[x],pos[y]));
return ans;
} int main()
{
n=read();
for(int i=;i<n;i++)
{
x=read();y=read();
add(x,y);add(y,x);
}
for(int i=;i<=n;i++) a[i]=read();
dfs1();dfs2(,);
build(,,maxsize);
for(int i=;i<=n;i++) insert(,pos[i],a[i]);
m=read();char ch[];
while(m--)
{
scanf("%s",ch);
scanf("%d%d",&x,&y);
if(ch[]=='C') a[x]=y,insert(,pos[x],y);
else{
if(ch[]=='M') printf("%d\n",solvemax(x,y));
else printf("%d\n",solvesum(x,y));
}
}
return ;
}

bzoj1036 树的统计(树链剖分+线段树)的更多相关文章

  1. BZOJ-1036 树的统计Count 链剖线段树(模板)=(树链剖分+线段树)

    潇爷昨天刚刚讲完...感觉得还可以...对着模板打了个模板...还是不喜欢用指针.... 1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Lim ...

  2. 【bzoj1036】树的统计[ZJOI2008]树链剖分+线段树

    题目传送门:1036: [ZJOI2008]树的统计Count 这道题是我第一次打树剖的板子,虽然代码有点长,但是“打起来很爽”,而且整道题只花了不到1.5h+,还是一遍过样例!一次提交AC!(难道前 ...

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

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

  4. 【BZOJ-2325】道馆之战 树链剖分 + 线段树

    2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 1153  Solved: 421[Submit][Statu ...

  5. 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树

    [BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...

  6. BZOJ2243 (树链剖分+线段树)

    Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...

  7. POJ3237 (树链剖分+线段树)

    Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...

  8. bzoj4034 (树链剖分+线段树)

    Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...

  9. HDU4897 (树链剖分+线段树)

    Problem Little Devil I (HDU4897) 题目大意 给定一棵树,每条边的颜色为黑或白,起始时均为白. 支持3种操作: 操作1:将a->b的路径中的所有边的颜色翻转. 操作 ...

  10. Aizu 2450 Do use segment tree 树链剖分+线段树

    Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show ...

随机推荐

  1. Window下的———TOMCAT环境的配置

    1. 先去官方网站下载需要的猫(tomcat) http://tomcat.apache.org/ 2.下载好包,然后解压出来,放在你需要的位置上 3.去到配环境变量的地方,进行相应的环境配置     ...

  2. oracle打开或者关闭flashback

    1.打开flashback: 关闭数据库 SQL>shutdown immediate; 启动到mount方式 SQL>startup mount; 如果归档没有打开,打开归档[因为fla ...

  3. ubuntu jdk和tomcat配置

    先查看linux的版通过file /sbin/init命令,下载对应版本的jdk. 我的ubuntu是64位的(桌面系统),所以下载的是jdk-7u71-linux-x64.tar.gz 在home的 ...

  4. jet flow in a combustion chamber

    Table of Contents 1. contacts 2. Paper digest 2.1. LES vs. RANS 2.2. Dynamics of Transient Fuel Inje ...

  5. Spring核心技术(二)——Spring的依赖及其注入

    本文将继续前文,描述Spring IoC中的依赖处理. 依赖 一般情况下企业应用不会只有一个对象(或者是Spring Bean).甚至最简单的应用都要多个对象来协同工作来让终端用户看到一个完整的应用的 ...

  6. 【Codeforces 675D】Tree Construction

    [链接] 我是链接,点我呀:) [题意] 依次序将数字插入到排序二叉树当中 问你每个数字它的父亲节点上的数字是啥 [题解] 按次序处理每一个数字 对于数字x 找到最小的大于x的数字所在的位置i 显然, ...

  7. pyhthon第一个小脚本——文件备份

    先说说这个脚本的作用:对指定路径的文件进行压缩备份到另一个指定的路径,并且压缩文件的文件名用当时的日期+时间命名. 先是对着<简明Python教程>上的代码敲的,一堆错误,书上给的是lin ...

  8. 50. Spring Boot日志升级篇—log4j【从零开始学Spring Boot】

    如果你使用的是spring boot 1.4.0版本的话,那么你可能需要配合以下文章进行学习 90.Spring Boot 1.4 使用log4j错误[从零开始学Spring Boot] Log4j是 ...

  9. MVC系统学习4—ModelMetaData

    在Mvc R2中,新引入了一些扩展方法,如后面带一个for的方法,这些扩展方法会根据Model的属性自定生成相应的Html元素,如Html.EditFor(Model=>Model.IsAppr ...

  10. Node & Express: some tips

    1. 设置Express端口号: 在app.js中添加 app.set('port', process.env.PORT || 3000); 之后命令行中打入 PORT=1234 node app.j ...