BZOJ 3531: [Sdoi2014]旅行(树链剖分+线段树)
解题思路
以每个颜色为根开一棵权值线段树,下标就是$dfs$序,其余都是基本操作,要动态开点。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=100005;
const int M=N*20;
inline int rd(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)) f=ch=='-'?0:1,ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
return f?x:-x;
}
inline int max(int x,int y) {return x>y?x:y;}
int n,q,head[N],cnt,to[N<<1],nxt[N<<1];
int C[N],W[N],siz[N],top[N];
int dep[N],id[N],fa[N],son[N],num,pool[N],cur;
struct Segment_tree{
int rt[N],sum[M],ls[M],rs[M],tot,Max[M];
inline int new_node(){
return (cur?(pool[cur--]):(++tot));
}
void update(int &x,int l,int r,int pos,int k){
if(!x) x=new_node();
if(l==r) {
sum[x]=k; Max[x]=k;
if(!k) pool[++cur]=x,x=0;
return;
}
int mid=(l+r)>>1;
if(pos<=mid) update(ls[x],l,mid,pos,k);
else update(rs[x],mid+1,r,pos,k);
sum[x]=sum[ls[x]]+sum[rs[x]];
Max[x]=max(Max[ls[x]],Max[rs[x]]);
if(!sum[x]) {pool[++cur]=x;x=0;}
}
int query_sum(int x,int l,int r,int L,int R){
if(!x) return 0; if(L<=l && r<=R) return sum[x];
int mid=(l+r)>>1,ret=0;
if(L<=mid) ret+=query_sum(ls[x],l,mid,L,R);
if(mid<R) ret+=query_sum(rs[x],mid+1,r,L,R);
return ret;
}
int query_max(int x,int l,int r,int L,int R){
if(!x) return 0; if(L<=l && r<=R) return Max[x];
int mid=(l+r)>>1,ret=0;
if(L<=mid) ret=max(ret,query_max(ls[x],l,mid,L,R));
if(mid<R) ret=max(ret,query_max(rs[x],mid+1,r,L,R));
return ret;
}
inline void BUILD(){
for(int i=1;i<=n;i++) update(rt[C[i]],1,n,id[i],W[i]);
}
}tree;
inline void add(int bg,int ed){
to[++cnt]=ed,nxt[cnt]=head[bg],head[bg]=cnt;
}
void dfs1(int x,int f,int d){
fa[x]=f; siz[x]=1; dep[x]=d;
int maxson=-1,u;
for(int i=head[x];i;i=nxt[i]){
u=to[i]; if(u==f) continue;
dfs1(u,x,d+1); siz[x]+=siz[u];
if(siz[u]>maxson) maxson=siz[u],son[x]=u;
}
}
void dfs2(int x,int topf){
id[x]=++num; top[x]=topf; if(!son[x]) return;
dfs2(son[x],topf); int u;
for(int i=head[x];i;i=nxt[i]){
u=to[i]; if(u==son[x] || u==fa[x]) continue;
dfs2(u,u);
}
}
inline int Qsum(int x,int y){
int ret=0,CC=C[y];
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
ret+=tree.query_sum(tree.rt[CC],1,n,id[top[x]],id[x]);
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
ret+=tree.query_sum(tree.rt[CC],1,n,id[x],id[y]);
return ret;
}
inline int Qmax(int x,int y){
int ret=0,CC=C[y];
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
ret=max(ret,tree.query_max(tree.rt[CC],1,n,id[top[x]],id[x]));
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
ret=max(ret,tree.query_max(tree.rt[CC],1,n,id[x],id[y]));
return ret;
}
int main(){
n=rd(),q=rd(); int x,y; char s[5];
for(int i=1;i<=n;i++) W[i]=rd(),C[i]=rd();
for(int i=1;i<n;i++){
x=rd(),y=rd();
add(x,y); add(y,x);
}
dfs1(1,0,0); dfs2(1,1); tree.BUILD();
while(q--){
scanf("%s",s+1); x=rd(),y=rd();
if(s[2]=='C') {
tree.update(tree.rt[C[x]],1,n,id[x],0); C[x]=y;
tree.update(tree.rt[C[x]],1,n,id[x],W[x]);
}
else if(s[2]=='W') tree.update(tree.rt[C[x]],1,n,id[x],y),W[x]=y;
else if(s[2]=='S') printf("%d\n",Qsum(x,y));
else printf("%d\n",Qmax(x,y));
}
return 0;
}
BZOJ 3531: [Sdoi2014]旅行(树链剖分+线段树)的更多相关文章
- B20J_3231_[SDOI2014]旅行_树链剖分+线段树
B20J_3231_[SDOI2014]旅行_树链剖分+线段树 题意: S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,城市信仰不同的宗教,为了方便,我们用不同的正整数代表各种宗教. S国 ...
- 洛谷P3313 [SDOI2014]旅行 题解 树链剖分+线段树动态开点
题目链接:https://www.luogu.org/problem/P3313 这道题目就是树链剖分+线段树动态开点. 然后做这道题目之前我们先来看一道不考虑树链剖分之后完全相同的线段树动态开点的题 ...
- 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路径上的 ...
随机推荐
- BZOJ 1818: [Cqoi2010]内部白点(树状数组)
传送门 解题思路 首先一定不可能有\(-1\)的情况,因为新产生的黑点不会造成任何贡献,它的各个方面都是不优的.那么只需要统计一遍答案,首先要将横坐标相同的两个点看成一条竖线,纵坐标相同的点看成一条横 ...
- [CSP-S模拟测试]:大新闻(主席树)
题目传送门(内部题20) 输入格式 第一行为两个数$n,m$,意义如题所述.接下来一行$n$个数,代表一开始$n$条大新闻的$naive$值.接下来$m$行,每行一个操作,输入格式如下:读入$1$,代 ...
- Vue&webpack入门实践
目录 1. 下载安装Vue 2. Vue 2.1 Vue要素 2.2 指令 2.3 组件化 2.4 vue-router 3. webpack 3.1 webpack简介 3.2 四个核心概念 3.3 ...
- 12. Jmeter-断言
jmeter-断言介绍与使用 性能测试中较少用到断言.断言会增加脚本执行时间,但是接口测试中断言是必备的.什么是断言?其实就是功能测试中常说的预期结果和实际结果是否相等. 响应断言 JSON Asse ...
- 学习contiki需要知道的一些概念和注意事项
概念: 1.宏:所谓宏,就是一些命令组织在一起,作为一个单独命令完成一个特定任务.Microsoft Word中对宏定义为:“宏就是能组织到一起作为一独立的命令使用的一系列word命令,它能使日常工作 ...
- 如何判断索引是否生效--explain
explain 显示了MySql 如何使用索引来处理select语句以及连接表. 使用方式在select 前面加上 explain就可以了 示例:explain select id , name ta ...
- 42.Flatten Binary Tree to Linked List
Level: Medium 题目描述: Given a binary tree, flatten it to a linked list in-place. For example, given ...
- Hibernate4教程五:事务和并发
Hibernate本身没有事务的实现 Hibernate 直接使用 JDBC 连接和 JTA 资源,不添加任何附加锁定行为.也就是说你在Hibernate里面使用的事务要么是JDBC的事务,要么是JT ...
- SetViewportOrgEx和SetWindowOrgEx
在MM_TEXT映射模式下使用这两个函数. 对于 BOOL SetViewportOrgEx( HDC hdc, // 设备内容HANDLE int X, // 新Viewport的x坐标 int Y ...
- keepalive+nginx
1Nginx+keepAlived负载均衡高可用1.1Nginx+keepAlive架构图 1.1.1主机宕机 1.1.2主机恢复 1.1.3高可用环境 两台nginx,一主一备:192.168.10 ...