codevs 2460 树的统计

http://codevs.cn/problem/2460/

2008年省队选拔赛浙江

 题目等级 : 大师 Master
 
题目描述 Description

一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。

我们将以下面的形式来要求你对这棵树完成一些操作:

  1. I.                    CHANGE u t : 把结点u的权值改为t
  2. II.                 QMAX u v: 询问从点u到点v的路径上的节点的最大权值
  3. III.               QSUM u v: 询问从点u到点v的路径上的节点的权值和

 

注意:从点u到点v的路径上的节点包括u和v本身

输入描述 Input Description

输入文件的第一行为一个整数n,表示节点的个数。

接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。

       接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。

接下来1行,为一个整数q,表示操作的总数。

接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。

输出描述 Output Description

对于每个“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

数据范围及提示 Data Size & Hint

对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。

树链剖分模板题,使用线段树维护

代码中变量含义:

n,节点个数    head[N],链表;
fa[N],存储父节点     son[N],统计包括自己在内的儿子个数

id[N], 给每个节点按树链剖分的顺序重新编号    dep[N],节点深度

bl[N],该节点所在重链的顶部节点    a[N],初始节点权值

struct node{int to,next;}e[N*2]; 链表
struct tree{int l,r,sum,maxx,size;}tr[N*2]; 线段树

注:代码中采用2*n空间方式建立线段树,k的左儿子为k+1,右儿子为k+k左儿子节点数*2
dfs_cnt,建立线段树时节点编号    cnt,链表    sz,树链剖分中节点访问顺序

#include<cstdio>
#include<algorithm>
#define N 30001
using namespace std;
int n,head[N];
int fa[N],son[N],id[N],dep[N],bl[N],a[N];
struct node{int to,next;}e[N*];
struct tree{int l,r,sum,maxx,size;}tr[N*];
int dfs_cnt,cnt,sz;
inline void insert(int u,int v)
{
e[++cnt].to=v;e[cnt].next=head[u];head[u]=cnt;
e[++cnt].to=u;e[cnt].next=head[v];head[v]=cnt;
}
void init()
{
scanf("%d",&n);
int u,v;
for(int i=;i<n;i++)
{
scanf("%d%d",&u,&v);
insert(u,v);
}
for(int i=;i<=n;i++) scanf("%d",&a[i]);
}
inline void build(int l,int r)
{
dfs_cnt++;tr[dfs_cnt].l=l;tr[dfs_cnt].r=r;tr[dfs_cnt].size=r-l+;
if(l==r) return;
int mid=l+r>>;
build(l,mid);build(mid+,r);
}
inline void dfs1(int k)
{
son[k]++;
for(int i=head[k];i;i=e[i].next)
{
if(e[i].to==fa[k]) continue;
fa[e[i].to]=k;
dep[e[i].to]=dep[k]+;
dfs1(e[i].to);
son[k]+=son[e[i].to];
}
}
inline void dfs2(int k,int chain)
{
int m=;sz++;
id[k]=sz;
bl[k]=chain;
for(int i=head[k];i;i=e[i].next)
{
if(e[i].to==fa[k]) continue;
if(son[e[i].to]>son[m]) m=e[i].to;
}
if(!m) return;
dfs2(m,chain);
for(int i=head[k];i;i=e[i].next)
{
if(e[i].to==m||e[i].to==fa[k]) continue;
dfs2(e[i].to,e[i].to);
}
}
inline void change(int k,int pos,int w)
{
if(tr[k].l==tr[k].r) {tr[k].sum=tr[k].maxx=w;return;}
int mid=tr[k].l+tr[k].r>>,l=k+,r=k+tr[k+].size*;
if(pos<=mid) change(l,pos,w);
else change(r,pos,w);
tr[k].sum=tr[l].sum+tr[r].sum;
tr[k].maxx=max(tr[l].maxx,tr[r].maxx);
}
inline int querymx(int k,int opl,int opr)
{
if(tr[k].l==opl&&tr[k].r==opr) return tr[k].maxx;
int mid=tr[k].l+tr[k].r>>,l=k+,r=k+tr[k+].size*;
if(opr<=mid) return querymx(l,opl,opr);
else if(opl>mid) return querymx(r,opl,opr);
else return max(querymx(l,opl,mid),querymx(r,mid+,opr));
}
inline int querysum(int k,int opl,int opr)
{
if(tr[k].l==opl&&tr[k].r==opr) return tr[k].sum;
int mid=tr[k].l+tr[k].r>>,l=k+,r=k+tr[k+].size*;
if(opr<=mid) return querysum(l,opl,opr);
else if(opl>mid) return querysum(r,opl,opr);
else return querysum(l,opl,mid)+querysum(r,mid+,opr);
}
inline void solvemx(int u,int v)
{
int ans=-0x7fffffff;
while(bl[u]!=bl[v])
{
if(dep[bl[u]]<dep[bl[v]]) swap(u,v);
ans=max(ans,querymx(,id[bl[u]],id[u]));
u=fa[bl[u]];
}
if(id[u]>id[v]) swap(u,v);
ans=max(ans,querymx(,id[u],id[v]));
printf("%d\n",ans);
}
inline void solvesum(int u,int v)
{
int ans=;
while(bl[u]!=bl[v])
{
if(dep[bl[u]]<dep[bl[v]]) swap(u,v);
ans+=querysum(,id[bl[u]],id[u]);
u=fa[bl[u]];
}
if(id[u]>id[v]) swap(u,v);
ans+=querysum(,id[u],id[v]);
printf("%d\n",ans);
}
void solve()
{
build(,n);
for(int i=;i<=n;i++)
change(,id[i],a[i]);
int q,u,v;char c[];
scanf("%d",&q);
for(int i=;i<=q;i++)
{
scanf("%s%d%d",c,&u,&v);
if(c[]=='C') change(,id[u],v);
else if (c[]=='M') solvemx(u,v);
else solvesum(u,v);
}
}
int main()
{
init();
dfs1();
dfs2(,);
solve();
}

2008ZJOI树的统计的更多相关文章

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

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

  2. bzoj1036 [ZJOI2008]树的统计Count

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

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

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

  4. 【BZOJ1036】[ZJOI2008]树的统计Count 树链剖分

    [BZOJ1036][ZJOI2008]树的统计Count Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. ...

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

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

  6. C++之路进阶——codevs2460(树的统计)

    2460 树的统计 2008年省队选拔赛浙江  时间限制: 2 s  空间限制: 128000 KB  题目等级 : 大师 Master       题目描述 Description 一棵树上有n个节 ...

  7. BZOJ 1036 树的统计-树链剖分

    [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 12904 Solved: 5191[Submit][Status ...

  8. BZOJ_1036_[ZJOI2008]_树的统计Conut_(树链剖分)

    描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1036 给出一棵树以及各点的权值,对数进行如下三种操作: 1.改变某一节点u的值为t; 2.求节 ...

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

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

随机推荐

  1. android 的helloworld没跑起来 原因

    <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com. ...

  2. 0422数学口袋精灵bug发现

    团队成员的博客园地址: 蔡彩虹:http://home.cnblogs.com/u/caicaihong/ 曾治业:http://www.cnblogs.com/zzy999/ 蓝叶:http://w ...

  3. PAT 甲级 1143 Lowest Common Ancestor

    https://pintia.cn/problem-sets/994805342720868352/problems/994805343727501312 The lowest common ance ...

  4. (三)使用Jmeter模拟300个用户登录

    1.首先在系统中创建300个用户(在这里使用 pl/sql 进行循环创建): 代码如下: --先对原先的表进行备份 :CREATE TABLE sys_user_bak AS SELECT * FRO ...

  5. [转帖]Linux 下 DD 命令的使用详解

    https://blog.csdn.net/noviblue/article/details/56012275 一.dd命令的解释 dd:用指定大小的块拷贝一个文件,并在拷贝的同时进行指定的转换. 注 ...

  6. Java中线程安全的集合

    如果多线程并发的访问与一个数据结构,那么很容易破坏一个数据结构. 例如,一个线程可能要向一个散列表中插入一条数据的过程中,被剥夺了控制权.如果另外一个线程也开始遍历同一个链表,很可能造成混乱,抛出异常 ...

  7. UVA11027_Palindromic Permutation

    此题不错.给你一些字字符,要求你用这些字符构成一个回文串,求字典序第k大的回文串. 首先通过给定的字符,我们可以直接判断能否构成回文串(奇数的字符不超过一种),其次可以统计每个字符在回文串的左边应该出 ...

  8. BZOJ 2521: [Shoi2010]最小生成树

    2521: [Shoi2010]最小生成树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 445  Solved: 262[Submit][Statu ...

  9. 51nod 1766 树上的最远点对 | LCA ST表 线段树 树的直径

    51nod 1766 树上的最远点对 | LCA ST表 线段树 树的直径 题面 n个点被n-1条边连接成了一颗树,给出a~b和c~d两个区间,表示点的标号请你求出两个区间内各选一点之间的最大距离,即 ...

  10. BZOJ2789 [Poi2012]Letters 【树状数组】

    题目链接 BZOJ 题解 如果我们给\(A\)中所有字母按顺序编号,给\(B\)中所有字母编上相同的号码 对于\(B\)中同一种,显然号码应该升序 然后求逆序对即可 #include<algor ...