BZOJ 3531(树链剖分+线段树)
Problem 旅行 (BZOJ 3531)
题目大意
给定一颗树,树上的每个点有两个权值(x,y)。
要求维护4种操作:
操作1:更改某个点的权值x。
操作2:更改某个点的权值y。
操作3:求a-->b路径上所有x属性与a,b相同的点y属性的和。
操作4:求a-->b路径上所有x属性与a,b相同的点y属性的最大值。
N,Q ,x <= 10^5 , y <= 10^4
解题分析
由于x属性的范围较大,无法直接统计。
考虑每次修改为单点修改,询问时只对相同x属性的询问。
因此,对于每个x属性开一棵线段树,询问时直接在相对应的线段树内查询。
开这么多棵线段树的话,就要动态开点,某个点的左右儿子的编号不是当前点编号的2倍或2倍加1。
参考程序
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std; #define N 10000008
#define V 100008
#define E 200008
#define lson l,m,ls[rt]
#define rson m+1,r,rs[rt] int n,Q,cnt;
int size[V],dep[V],fa[V],son[V],w[V],top[V],rk[V],root[V];
int a[V],c[V]; struct line{
int u,v,nt;
}eg[E];
int lt[V],sum; void adt(int u,int v){
eg[++sum].u=u; eg[sum].v=v; eg[sum].nt=lt[u]; lt[u]=sum;
}
void add(int u,int v){
adt(u,v); adt(v,u);
} struct segment_tree{
int sum[N],mx[N],ls[N],rs[N];
void pushup(int rt){
sum[rt]=sum[ls[rt]]+sum[rs[rt]];
mx[rt]=max(mx[ls[rt]],mx[rs[rt]]);
}
void update(int x,int val,int l,int r,int &rt){ //============ 这个 & 符号用得还是蛮精髓的 ====================
if (rt==) rt=++cnt;
if (l==r){
sum[rt]=val;
mx[rt]=val;
return;
}
int m=(l+r)/;
if (x <= m) update(x,val,lson);
if (m < x) update(x,val,rson);
pushup(rt);
}
int query_sum(int L,int R,int l,int r,int rt){
if (L<=l && r<=R){
return sum[rt];
}
int m=(l+r)/;
int res=;
if (L <= m) res+=query_sum(L,R,lson);
if (m < R) res+=query_sum(L,R,rson);
return res;
}
int query_max(int L,int R,int l,int r,int rt){
if (L<=l && r<=R){
return mx[rt];
}
int m=(l+r)/;
int res=;
if (L <= m) res=max(res,query_max(L,R,lson));
if (m < R) res=max(res,query_max(L,R,rson));
return res;
}
}T; void dfs_1(int u){
dep[u]=dep[fa[u]]+; size[u]=; son[u]=;
for (int i=lt[u];i;i=eg[i].nt){
int v=eg[i].v;
if (v==fa[u]) continue;
fa[v]=u;
dfs_1(v);
size[u]+=size[v];
if (size[v]>size[son[u]]) son[u]=v;
}
}
void dfs_2(int u,int tp){
top[u]=tp; w[u]=++cnt; rk[cnt]=u;
if (son[u]) dfs_2(son[u],tp);
for (int i=lt[u];i;i=eg[i].nt){
int v=eg[i].v;
if (v==fa[u] || v==son[u]) continue;
dfs_2(v,v);
}
}
void solve_sum(int x,int y){
int res=,cl=c[x];
while (top[x]!=top[y]){
if (dep[top[x]]<dep[top[y]]) swap(x,y);
res+=T.query_sum(w[top[x]],w[x],,n,root[cl]);
x=fa[top[x]];
}
if (dep[x]>dep[y]) swap(x,y);
res+=T.query_sum(w[x],w[y],,n,root[cl]);
printf("%d\n",res);
}
void solve_max(int x,int y){
int res=,cl=c[x];
while (top[x]!=top[y]){
if (dep[top[x]]<dep[top[y]]) swap(x,y);
res=max(res,T.query_max(w[top[x]],w[x],,n,root[cl]));
x=fa[top[x]];
}
if (dep[x]>dep[y]) swap(x,y);
res=max(res,T.query_max(w[x],w[y],,n,root[cl]));
printf("%d\n",res);
} int main(){
memset(lt,,sizeof(lt)); sum=;
scanf("%d %d",&n,&Q);
for (int i=;i<=n;i++) scanf("%d %d",&a[i],&c[i]);
for (int i=;i<n;i++){
int u,v;
scanf("%d %d",&u,&v);
add(u,v);
}
dfs_1();
dfs_2(,);
cnt=;
for (int i=;i<=n;i++) T.update(w[i],a[i],,n,root[c[i]]);
while (Q--){
char x[];
int y,z;
scanf("%s%d%d",x,&y,&z);
if (strcmp(x,"CC")==){
T.update(w[y],,,n,root[c[y]]);
c[y]=z;
T.update(w[y],a[y],,n,root[c[y]]);
}
if (strcmp(x,"CW")==){
a[y]=z; // ====================== debug ============//
T.update(w[y],z,,n,root[c[y]]);
}
if (strcmp(x,"QS")==){
solve_sum(y,z);
}
if (strcmp(x,"QM")==){
solve_max(y,z);
}
}
}
BZOJ 3531(树链剖分+线段树)的更多相关文章
- BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 )
BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 ) 题意分析 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 ...
- BZOJ.1036 [ZJOI2008]树的统计Count ( 点权树链剖分 线段树维护和与最值)
BZOJ.1036 [ZJOI2008]树的统计Count (树链剖分 线段树维护和与最值) 题意分析 (题目图片来自于 这里) 第一道树链剖分的题目,谈一下自己的理解. 树链剖分能解决的问题是,题目 ...
- BZOJ 3672[NOI2014]购票(树链剖分+线段树维护凸包+斜率优化) + BZOJ 2402 陶陶的难题II (树链剖分+线段树维护凸包+分数规划+斜率优化)
前言 刚开始看着两道题感觉头皮发麻,后来看看题解,发现挺好理解,只是代码有点长. BZOJ 3672[NOI2014]购票 中文题面,题意略: BZOJ 3672[NOI2014]购票 设f(i)f( ...
- bzoj 4196 [Noi2015]软件包管理器 (树链剖分+线段树)
4196: [Noi2015]软件包管理器 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 2852 Solved: 1668[Submit][Sta ...
- bzoj 2157: 旅游【树链剖分+线段树】
裸的树链剖分+线段树 但是要注意一个地方--我WA了好几次才发现取完相反数之后max值和min值是要交换的-- #include<iostream> #include<cstdio& ...
- BZOJ 3589 动态树 (树链剖分+线段树)
前言 众所周知,90%90\%90%的题目与解法毫无关系. 题意 有一棵有根树,两种操作.一种是子树内每一个点的权值加上一个同一个数,另一种是查询多条路径的并的点权之和. 分析 很容易看出是树链剖分+ ...
- 【BZOJ-2325】道馆之战 树链剖分 + 线段树
2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 1153 Solved: 421[Submit][Statu ...
- 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树
[BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...
- BZOJ2243 (树链剖分+线段树)
Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...
- POJ3237 (树链剖分+线段树)
Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...
随机推荐
- JS回调函数(callback)
在使用Jquery的时候,用到Callback(),回调函数的概念.而且很多. 比如: $.ajax({ url:"test.json", type: "GET" ...
- iOS开发UIScrollView的底层实现
起始 做开发也有一段时间了,经历了第一次完成项目的激动,也经历了天天调用系统的API的枯燥,于是就有了探索底层实现的想法. 关于scrollView的思考 在iOS开发中我们会大量用到scrollVi ...
- 读书笔记1: 资源地址—通用资源的标识符(URI)
例子: https://msdn.microsoft.com/zh-cn/library/system.uri(v=vs.110).aspx 解释:协议://主机[:端口号]/绝对路径[参数] 对应的 ...
- Andriod使用webview控件往APP里内嵌网页
转自博文:http://www.cnblogs.com/JuneZhang/p/4148542.html 1.布局文件片段:res-layout <WebView android:id=&quo ...
- 20145236 《Java程序设计》课程总结
20145236 <Java程序设计>课程总结 一.每周读书笔记链接汇总 第一周读书笔记 第二周读书笔记 第三周读书笔记 第四周读书笔记 第五周读书笔记 第六周读书笔记 第七周读书笔记 第 ...
- 数据库索引<二> 补充前篇
你要准备的软件有: 最新版 Rsync for windows 服务端:cwRsync_Server_2.1.5_Installer.zip 客户端:cwRsync_2.1.5_Installer.z ...
- 学习记录008-crond和visudo
1.每隔两个小时将/etc/servers文件打包备份到.tmp下(每次名字不同) [root@kaka cc.log]# tar zcvf /server/backup/ccc.log_$(date ...
- 绑定本地Service并与之通信-----之一
import android.app.Service;import android.content.Intent;import android.os.Binder;import android.os. ...
- TFS错误 TF31004:在连接带xxx.xxx.xxx.xxx上的Team Foundation Server时遇到错误。请等待几分钟,然后重试。如果问题仍然存在,请与服务器管理员联系
- python中的urlencode与urldecode
当url地址含有中文,或者参数有中文的时候,这个算是很正常了,但是把这样的url作为参数传递的时候(最常见的callback),需要把一些中文甚至'/'做一下编码转换. 所以对于一些中文或者字符,ur ...