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) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...
随机推荐
- SQL Server数据库(SQL Sever语言 存储过程及触发器)
存储过程:就像函数一样的会保存在数据库中-->可编程性-->存储过程 创建存储过程: 保存在数据库表,可编程性,存储过程create proc jiafa --需要的参数@a int,@b ...
- word-wrap word-break white-space 用法。
一.word-wrap使用: 语法: word-wrap : normal | break-word 取值说明: 1.normal和break-word,其中normal为默认值,当其值为normal ...
- Apache网页有时能访问,有时超时打不开
在win server 2008上安装wamp2.4版本,配置apache 访问网页一直在加载,似乎被挂起. 转圈需要3分钟多钟, 最终显示无法访问. 或者超时. 错误日志中有如下提示: [Sat J ...
- c# 调用 ShellExecute
using System.Runtime.InteropServices; namespace ConsoleTest{ class Program { public enu ...
- Mongoose 是什么?
Mongoose 参考手册 标签(空格分隔): MongoDB 一般我们不直接用MongoDB的函数来操作MongoDB数据库 Mongose就是一套操作MongoDB数据库的接口. Schema 一 ...
- win10 ctrl + 空格 热键取消
关键:添加English,并上移到第一,即开机默认即可.Win8+不用修改注册表的,只有win7里才可能需要修改注册表. http://superuser.com/questions/327479/c ...
- ios应用数据存储的常用方式 ios7.1应用沙盒
归档:用某种格式保存某个对象,又称持久化. 1XML 属性列表plist归档(持久化) 2Preference(偏好设置) 3NSKeyedArchiver归档 4SQLite3 5Core Data ...
- Unity场景道具模型拓展自定义编辑器
(一)适用情况 当游戏主角进入特定的场景或者关卡,每个关卡需要加载不同位置的模型,道具等.这些信息需要先在unity编辑器里面配置好,一般由策划干这事,然后把这些位置道具信息保存在文件,当游戏主角进入 ...
- T420修改wifi灯闪动模式
给T420新装了centos7发现默认的配置wifi灯是工作时闪动的,有点晃眼,想改成简单的on 的时候常亮,off的时候常暗的模式 添加配置文件: vi /etc/modprobe.d/wlanle ...
- mybatis分页插件PageHelper的使用(转)
Mybatis 的分页插件PageHelper-4.1.1的使用 Mybatis 的分页插件 PageHelper 项目地址:http://git.oschina.net/free/Mybatis_P ...