1036: [ZJOI2008]树的统计Count

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 14982  Solved: 6081
[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

——————————————题解

毕竟是模板……

所谓的线段树维护链,就是建很多个线段树,节点一个挨着一个省空间

代码量……真是……

 //大家吼,我要砍树了
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <set>
#include <vector>
#include <string.h>
#define siji(i,x,y) for(int i=(x);i<=(y);++i)
#define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
#define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
#define sigongzi(j,x,y) for(int j=(x);j>(y);--j)
#define inf 0x7fffffff
//#define ivorysi
#define mo 97797977
#define hash 974711
#define base 47
#define MAXN 30005
#define fi first
#define se second
#define pii pair<int,int>
using namespace std;
//树的存储
struct node {
int to,next;
}edge[MAXN*];
int head[MAXN],sumedge,n,q;
int val[MAXN];//点值 void add(int u,int v) {
edge[++sumedge].to=v;
edge[sumedge].next=head[u];
head[u]=sumedge;
}
//线段树部分变量定义
struct data {
int l,r,//边界
lson,//左儿子(因为不能直接位运算要节省空间)
rson,//右儿子(因为不能直接位运算要节省空间)
sum,//区间总和
maxp,//区间最大值
fa;//单点更新优化
data() {
l=,r=,lson=,rson=,sum=,maxp=-inf,fa=;
}
}tree[MAXN*];
int treecnt;//树点个数
int w[MAXN];//单点更新优化 //剖分部分变量定义
int fa[MAXN],//父亲
dep[MAXN],//深度
size[MAXN],//子树大小
son[MAXN],//重儿子
rank[MAXN],//在链中的位置
belong[MAXN],//属于哪条链
top[MAXN],//这个点所在链的深度最小的点
linkcnt,//链数
lroot[MAXN];//每条链的树根 //剖分部分
void dfs1(int u) {//size,fa,son,dep
size[u]=;
for(int i=head[u];i;i=edge[i].next) {
int v=edge[i].to;
if(v!=fa[u]) {
fa[v]=u;
dep[v]=dep[u]+;
dfs1(v);
size[u]+=size[v];
if(size[v]>size[son[u]]) son[u]=v;
}
}
}
void build(int p,int l,int r);
vector<int> line;
void dfs2(int u) {//belong,top,rank
if(!belong[u]) {
belong[u]=++linkcnt;
top[linkcnt]=u;
rank[u]=; }
line.push_back(u);
if(!son[u]) {
lroot[belong[u]]=++treecnt;
build(treecnt,,line.size());
line.clear();
return;
}
belong[son[u]]=belong[u];
rank[son[u]]=rank[u]+;
dfs2(son[u]);
for(int i=head[u];i;i=edge[i].next) {
int v=edge[i].to;
if(v!=son[u] && v!=fa[u])
dfs2(v);
} }
//剖分部分结束
//————————————————————————————
//线段树部分
void build(int p,int l,int r) {
tree[p].l=l;
tree[p].r=r;
if(l==r) {
tree[p].sum=val[line[l-]];
tree[p].maxp=val[line[l-]];
w[line[l-]]=p;
return;
}
int mid=(l+r)>>;
tree[p].lson=++treecnt;
tree[treecnt].fa=p;
build(treecnt,l,mid);
int t1=tree[tree[p].lson].maxp;
int t3=tree[tree[p].lson].sum;
tree[p].rson=++treecnt;
tree[treecnt].fa=p;
build(treecnt,mid+,r);
int t2=tree[tree[p].rson].maxp;
int t4=tree[tree[p].rson].sum;
tree[p].sum+=t3+t4;
tree[p].maxp=max(t1,t2);
return;
}
void change(int u) {
tree[w[u]].sum=tree[w[u]].maxp=val[u];
int z=tree[w[u]].fa;
while(z!=) {
tree[z].sum=tree[tree[z].lson].sum+tree[tree[z].rson].sum;
tree[z].maxp=max(tree[tree[z].lson].maxp,tree[tree[z].rson].maxp);
z=tree[z].fa;
}
}
int treeqsum(int p,int l,int r) {
if(l <= tree[p].l && r >= tree[p].r) {
return tree[p].sum;
}
int mid=(tree[p].l+tree[p].r)>>;
int t1=,t2=;
if(l <= mid) {
t1=treeqsum(tree[p].lson,l,r);
}
if(r > mid){
t2=treeqsum(tree[p].rson,l,r);
}
return t1+t2;
}
int treeqmax(int p,int l,int r) {
if(l <= tree[p].l && r >= tree[p].r) {
return tree[p].maxp;
}
int mid=(tree[p].l+tree[p].r)>>;
int t1=-inf,t2=-inf;
if(l <= mid) {
t1=treeqmax(tree[p].lson,l,r);
}
if(r > mid){
t2=treeqmax(tree[p].rson,l,r);
}
return max(t1,t2);
}
//线段树部分结束
//——————————————————————————
//解决问题部分
int qsum(int u,int v){
int x=top[belong[u]],y=top[belong[v]],res=;
while(belong[u]!=belong[v]) {
if(dep[x]>dep[y]){
res+=treeqsum(lroot[belong[x]],tree[lroot[belong[x]]].l,rank[u]);
u=fa[x];
}
else {
res+=treeqsum(lroot[belong[y]],tree[lroot[belong[y]]].l,rank[v]);
v=fa[y];
}
x=top[belong[u]],y=top[belong[v]];
}
x=max(rank[u],rank[v]);
y=rank[u]+rank[v]-x;
res+=treeqsum(lroot[belong[u]],y,x);
return res; }
int qmax(int u,int v) {
int x=top[belong[u]],y=top[belong[v]],res=-inf;
while(belong[x]!=belong[y]) {
if(dep[x]>dep[y]){
res=max(res,treeqmax(lroot[belong[x]],tree[lroot[belong[x]]].l,rank[u]));
u=fa[x];
}
else {
res=max(res,treeqmax(lroot[belong[y]],tree[lroot[belong[y]]].l,rank[v]));
v=fa[y];
}
x=top[belong[u]],y=top[belong[v]];
}
x=max(rank[u],rank[v]);
y=rank[u]+rank[v]-x;
res=max(res,treeqmax(lroot[belong[u]],y,x));
return res;
}
void prepare() {
int u,v;
scanf("%d",&n);
xiaosiji(i,,n) {
scanf("%d %d",&u,&v);
add(u,v),add(v,u);
}
siji(i,,n) {
scanf("%d",&val[i]);
}
scanf("%d",&q);
dfs1(),dfs2();
}
void solve() {
prepare();
char ord[];
siji(i,,q) {
scanf("%s",ord);
if(ord[]=='C') {
int u;
scanf("%d",&u);
//之前写成scanf("%d%d",&u,&val[u]);应该是因为它获得的是原来的u,可能是个很大的野值
scanf("%d",&val[u]);
change(u);
}
else if(ord[]=='M') {
int u,v;
scanf("%d%d",&u,&v);
printf("%d\n",qmax(u,v));
}
else {
int u,v;
scanf("%d%d",&u,&v);
printf("%d\n",qsum(u,v));
}
}
}
int main(int argc, char const *argv[])
{
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
solve();
}

BZOJ 1036: [ZJOI2008]树的统计Count (树链剖分模板题)的更多相关文章

  1. Cogs 1688. [ZJOI2008]树的统计Count(树链剖分+线段树||LCT)

    [ZJOI2008]树的统计Count ★★★ 输入文件:bzoj_1036.in 输出文件:bzoj_1036.out 简单对比 时间限制:5 s 内存限制:162 MB [题目描述] 一棵树上有n ...

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

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

  3. BZOJ 2243 染色 | 树链剖分模板题进阶版

    BZOJ 2243 染色 | 树链剖分模板题进阶版 这道题呢~就是个带区间修改的树链剖分~ 如何区间修改?跟树链剖分的区间询问一个道理,再加上线段树的区间修改就好了. 这道题要注意的是,无论是线段树上 ...

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

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

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

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

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

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

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

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

  8. BZOJ 1036 [ZJOI2008]树的统计Count (树链剖分)(线段树单点修改)

    [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 14968  Solved: 6079[Submit][Stat ...

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

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

随机推荐

  1. day19 IO编程

    文件:文件是数据源(保存数据的地方)的一种. 文件在程序中是以流的形式来操作的 内存(程序)到文件是输出流,文件到内存(程序)是输入流. 字节流:可用于读写的二进制文件及任何类型文件. 字符流:可以用 ...

  2. day11 细节记忆

    单一职责:一个方法只做一件事. 值传递——java只有值传递. gender(性别) male(男)female(女) 自动生成的set.get方法中,布尔类型的get方法需要手工改为get(默认是i ...

  3. Ubuntu 搭建svn服务器 ,以及常见错误解决方案

    一.安装命令: 1)以root身份登录.执行:sudo su -命令 2)执行安装命令:apt-get install subversion   二.创建项目目录 1)mkdir  /home/svn ...

  4. git爬坑不完全指北(一):Permission to xxx.git denied to user的解决方案

    由于对之前github账户名不太满意,又不像大神一样需要两个账号绑定.所以今天注册了新账号,想把电脑绑定到新账号上,结果就踩坑了……报错如标题. 在网上按照这个题目可以搜索出一大堆的解决方案,但都是一 ...

  5. noi题库(noi.openjudge.cn) 3.9数据结构之C++STL T1——T2

    T1 1806:词典 描述 你旅游到了一个国外的城市.那里的人们说的外国语言你不能理解.不过幸运的是,你有一本词典可以帮助你. 输入首先输入一个词典,词典中包含不超过100000个词条,每个词条占据一 ...

  6. Redis学习三:Redis数据类型

    一.Redis的五大数据类型 1.String(字符串) string是redis最基本的类型,你可以理解成与Memcached一模一样的类型,一个key对应一个value.string类型是二进制安 ...

  7. 你需要了解 Windows Phone 8.1 的11件事

    微软已经发布了其新一代手机操作系统 Windows Phone 8.1,拥有一些新的特性.从本质上来说,微软此次的大修让 Windows Phone 更接近 Android 和 iOS,对于使用体验的 ...

  8. 20155323 2016-2017-2 《Java程序设计》第7周学习总结

    20155323 2016-2017-2 <Java程序设计>第7周学习总结 使用Lambda语法来代替匿名的内部类,代码不仅简洁,而且还可读. 时间的度量:GMT.UT.TAI.UTC. ...

  9. POJ 3783 Balls --扔鸡蛋问题 经典DP

    题目链接 这个问题是谷歌面试题的加强版,面试题问的是100层楼2个鸡蛋最坏扔多少次:传送门. 下面我们来研究下这个题,B个鸡蛋M层楼扔多少次. 题意:给定B (B <= 50) 个一样的球,从 ...

  10. 矩阵 matrix

    传送门 注意这题时限是2s [问题描述] 有一个n × m的矩阵,你从左上角走到右下角,只能向下和向右走. 每个点上有一个重量v i,j 价值w i,j 的物品,你有一个容量为S的背包,经过一个点你可 ...