P2590 [ZJOI2008]树的统计

题目描述

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

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

I. CHANGE u t : 把结点u的权值改为t

II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值

III. QSUM u v: 询问从点u到点v的路径上的节点的权值和

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

输入输出格式

输入格式:

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

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

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

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

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

输出格式:

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

输入输出样例

输入样例#1:

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

输出样例#1:

4
1
2
2
10
6
5
6
5
16

说明

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

思路:树链剖分模板题。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAXN 1000000
using namespace std;
int n,q,sz,tot;
int w[MAXN],id[MAXN];
int dad[MAXN],deep[MAXN],size[MAXN],top[MAXN];
int to[MAXN],head[MAXN],net[MAXN];
struct nond{int l,r,dis,sum;
}tree[MAXN];
void add(int u,int v){to[++tot]=v;net[tot]=head[u];head[u]=tot;to[++tot]=u;net[tot]=head[v];head[v]=tot;
}
void up(int now){tree[now].sum=tree[now*2].sum+tree[now*2+1].sum;tree[now].dis=max(tree[now*2].dis,tree[now*2+1].dis);
}
void build(int now,int l,int r){tree[now].l=l;tree[now].r=r;if(tree[now].l==tree[now].r)return ;int mid=(tree[now].l+tree[now].r)/2;build(now*2,l,mid);build(now*2+1,mid+1,r);
}
void change(int now,int x,int k){if(tree[now].l==tree[now].r){tree[now].dis=k;tree[now].sum=k;return ;}int mid=(tree[now].l+tree[now].r)/2;if(x<=mid)    change(now*2,x,k);else if(x>mid)    change(now*2+1,x,k);up(now);
}
int query(int now,int l,int r,int z){if(tree[now].l==l&&tree[now].r==r){if(z==1)    return tree[now].dis;else if(z==0)    return tree[now].sum;}int mid=(tree[now].l+tree[now].r)/2;if(r<=mid)    return query(now*2,l,r,z);else if(l>mid)    return query(now*2+1,l,r,z);else{if(z==1)return max(query(now*2,l,mid,z),query(now*2+1,mid+1,r,z));else if(z==0)return query(now*2,l,mid,z)+query(now*2+1,mid+1,r,z);}
}
void dfs(int x){size[x]=1;deep[x]=deep[dad[x]]+1;for(int i=head[x];i;i=net[i])if(dad[x]!=to[i]){dad[to[i]]=x;dfs(to[i]);size[x]+=size[to[i]];}
}
void dfs1(int x){int t=0;id[x]=++sz;if(!top[x])    top[x]=x;change(1,sz,w[x]);for(int i=head[x];i;i=net[i])if(dad[x]!=to[i]&&size[t]<size[to[i]])t=to[i];if(t){top[t]=top[x];dfs1(t);}for(int i=head[x];i;i=net[i])if(dad[x]!=to[i]&&t!=to[i])dfs1(to[i]);
}
int squery(int x,int y,int z){int ans;if(z==1)    ans=-0x7f7f7f7f;else ans=0;while(top[x]!=top[y]){if(deep[top[x]]<deep[top[y]])    swap(x,y);if(z==1)    ans=max(ans,query(1,id[top[x]],id[x],1));else    ans+=query(1,id[top[x]],id[x],0);x=dad[top[x]];}if(id[x]>id[y])    swap(x,y);if(z==1)    ans=max(ans,query(1,id[x],id[y],1));else    ans+=query(1,id[x],id[y],0);return ans;
}
int main(){scanf("%d",&n);for(int i=1;i<n;i++){int u,v;scanf("%d%d",&u,&v);add(u,v);}for(int i=1;i<=n;i++)scanf("%d",&w[i]);build(1,1,n);dfs(1);dfs1(1);scanf("%d",&q);for(int i=1;i<=q;i++){char a[10];int u,v;scanf("%s%d%d",a,&u,&v);if(a[1]=='H')change(1,id[u],v);else if(a[1]=='M')printf("%d\n",squery(u,v,1));elseprintf("%d\n",squery(u,v,0));}
}

转载于:https://www.cnblogs.com/cangT-Tlan/p/7404486.html

洛谷 P2590 [ZJOI2008]树的统计相关推荐

  1. 洛谷——P2590 [ZJOI2008]树的统计(树链剖分模板练手)

    P2590 [ZJOI2008]树的统计 I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问 ...

  2. [luogu P2590 ZJOI2008] 树的统计 (树链剖分)

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

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

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 3427  Solved: 1429 [Submi ...

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

    树链剖分: 把一棵树剖分为若干条链,然后利用数据结构(树状数组,SBT,Splay,线段树等等)去维护每一条链,复杂度 为O(logn),总体复杂度O(nlog²n) 步骤: ①将树的边分成重边和轻边 ...

  5. 洛谷 P3373 线段树2

    洛谷 P3373 线段树2 mul和pls更新某区间左右子树sum的时候,别忘了回头更新这个区间的sum 只有在传递给子序列之后,父序列的lz标记才能清零.其他时候,lz标记只增不减 #include ...

  6. 洛谷P3373线段树

    洛谷P3373 线段树模板题,主要对懒标的处理要求比较高. 有三种操作: 区间加法 区间乘法 区间求和查询 tips:我们对一个区间进行乘k操作的时候,他之前可能存在加法lazy还没pushdown, ...

  7. 信息学奥赛一本通 1400:统计单词数 | 1954:【11NOIP普及组】统计单词数 | OpenJudge NOI 1.12 05 | 洛谷 P1308 [NOIP2011 普及组] 统计单词数

    [题目链接] ybt 1400:统计单词数 ybt 1954:[11NOIP普及组]统计单词数 OpenJudge NOI 1.12 05:统计单词数 洛谷 P1308 [NOIP2011 普及组] ...

  8. 信息学奥赛一本通 1239:统计数字 | 1847:【07NOIP提高组】统计数字 | OpenJudge NOI 2.4 7909 | 洛谷 P1097 [NOIP2007 提高组] 统计数字

    [题目链接] ybt 1239:统计数字 ybt 1847:[07NOIP提高组]统计数字 一本通中限制不许使用STL,那么引入头文件不能写<bits/stdc++.h>,只能写<i ...

  9. 洛谷P1554——梦中的统计 解法(C++)

    Hi 让大家久等了 今天再再再再再再再再再再再...来一道洛谷的题 梦中的统计(你们是不是已经厌烦了洛谷) 老规矩,先上个题目传送门(点击蓝字即可观看) 题目背景 Bessie 处于半梦半醒的状态.过 ...

最新文章

  1. 百度的卡尔曼滤波的解释
  2. 使用HtmlHelper 写自己的 mvc 分页
  3. lvs,keepalived做HA
  4. 如何将zipoutputstream返回_excel:vlookup如何区间查找?如何使用通配符?如何多条件查找?...
  5. 以整体思维看问题:解决单页应用,系统角色请求覆盖身份唯一标识(本项目中是session_id命名的)发送请求问题...
  6. mapreduce文本排序_MapReduce:通过数据密集型文本处理
  7. nginx日志定期归档脚本
  8. 深入分析linux内核源码
  9. 总结(6)--- python基础知识点小结(细全)
  10. javaweb时间插件
  11. 学习 Java全栈工程师6.0 初学者笔记1 2021-08-09
  12. 配置authorized_keys让服务器A免密登录服务器B
  13. leetcode加一
  14. abstract 抽象学习
  15. 《无聊教程●第一课●教你编一个牛逼的VBScript邮件发送器》
  16. ARTS-第-22-期
  17. 前端根据后端返回数据导出指定样式的表格(xlsx-js-style)
  18. STM32F407使用SPI读写SD TF卡(不能读取 会卡死)
  19. JSP运行原理 九大内置对象 四大作用域
  20. likeshop外卖点餐系统【100%开源无加密】

热门文章

  1. 友盟QQ好友或者空间分享成功,但回调失败或取消
  2. 代码优化 5 大原则,第一条就是别优化了!!!
  3. 三百年前的AI骗局:骗过美国总统和普鲁士大帝的国际象棋AI
  4. 比特币拒绝第 340 次“被死亡”
  5. 这个程序员如何以一己之力阻止了 Bug 代码的提交并改变整个 DevOps 世界?
  6. 《深入理解 Java 内存模型》读书笔记(下)(干货,万字长文)
  7. 网络:XSS和HttpOnly
  8. 数据库:悲观锁与乐观锁
  9. SO_REUSEADDR和SO_REUSEPORT
  10. Android --- java.lang.RuntimeException: Can‘t create handler inside thread that has not called Loop