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) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...
随机推荐
- codeforces723 D. Lakes in Berland(并查集)
题目链接:codeforces723 D. Lakes in Berland 参考博客:http://www.cnblogs.com/Geek-xiyang/p/5930245.html #inclu ...
- String.equals()方法的实现代码,
通常对String的比较有两种情况,一个是使用==,另一个是使用equals()方法,注意==是对对象的地址进行比较的,而String中的equals()方法是覆盖了Object类的方法,并且实现为对 ...
- apache 修改最大连接数
1.在哪里设置? 服务器的为FreeBSD 6.2 ,apache 2.24,使用默认配置(FreeBSD 默认不加载自定义MPM配置),默认最大连接数是250 在/usr/local/etc/apa ...
- 安装Adobe Dreamweaver CS6 免序列号 官方破解版
Adobe Dreamweaver CS6 免序列号 官方破解版 Adobe Dreamweaver CS6是世界顶级软件厂商Adobe推出的一套可视化的网页开发工具,Dreamweaver CS6最 ...
- POJ 1202 Family 概率,DP,高精 难度:2
http://poj.org/problem?id=1202 难度集中在输出格式上,因为输出格式所以是高精度 递推式: 血缘肯定只有从双亲传到儿子的,所以,设f,m为双亲,son为儿子,p[i][j] ...
- 一模 (1) day2
第一题:(水题) 题目大意:就是给出扫雷的图,然后统计每个九宫格的雷的个数. 解题过程: 1.好久没做这样的水题了.直接模拟水过.. 第二题: 题目大意:给出一个长度小于1000的数k,要求一个尽可能 ...
- https://github.com/oneuijs/You-Dont-Need-jQuery
https://github.com/oneuijs/You-Dont-Need-jQuery
- 开通了cnblogs
受够了百度空间,换个地方,或许会更好. 以后有机会会将百度空间你的文章搬过来的.
- JAVA每日一记
1.两个最基本的java回收算法:复制算法和标记清理算法 复制算法:两个区域A和B,初始对象在A,继续存活的对象被转移到B.此为新生代最常用的算法 ...
- SharePoint安全 - 在Goolge和Bing中查找SharePoint相关内容
博客地址 http://blog.csdn.net/foxdave 本篇提供两个查询串字典,分别对应Google和Bing的搜索,用来查询SharePoint网站的相关内容 Google ShareP ...