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路径上的 ...
随机推荐
- 企业资源计划(ERP)
ERP(企业资源计划)一般指企业资源计划(ERP) 物资资源管理(物流).人力资源管理(人流).财务资源管理(财流).信息资源管理(信息流) 信息技术在企业管理学上的应用可分做如下发展阶段:A. MI ...
- LOJ 2555 「CTSC2018」混合果汁——主席树
题目:https://loj.ac/problem/2555 二分答案,在可以选的果汁中,从价格最小的开始选. 按价格排序,每次可以选的就是一个前缀.对序列建主席树,以价格为角标,维护体积和.体积*价 ...
- DB-概念-数据库:数据库/Database
ylbtech-DB-概念-数据库:数据库/Database 数据库是以一定方式储存在一起.能与多个用户共享.具有尽可能小的冗余度.与应用程序彼此独立的数据集合,可视为电子化的文件柜——存储电子文件的 ...
- ajax请求controller出现中文乱码
ajax请求controller出现中文乱码 解决方法:在 @RequestMapping 中加上 produces = {"application/json;charset=UTF-8& ...
- HDU 3466 Proud Merchants(01背包)
题目链接: 传送门 Proud Merchants Time Limit: 1000MS Memory Limit: 65536K Description Recently, iSea wen ...
- for语句和if语句画正方形菱形
public static void main(String[] args) { int n =8; // 空心正方形 for(int i=0;i<=n;i++){ if(i==0||i==n) ...
- Oracle 11g Compound Trigger
Original Link In Oracle 11g, the concept of compound trigger was introduced. A compound trigger is a ...
- go语言统计字符个数
具体代码如下: package main import "fmt" func main() { m := make(map[rune]int, 1) var input strin ...
- Python基础代码1
Python基础代码 import keyword#Python中关键字 print(keyword.kwlist) ['False', 'None', 'True', 'and', 'as', 'a ...
- 各种Web服务器与Nginx的对比
Tomcat和Jetty面向Java语言,先天就是重量级的Web服务器,它们的性能与Nginx没有可比性. IIS只能在windows操作系统上运行,Windows作为服务器在稳定性与其他一些性能上都 ...