传送门

解题思路

  以每个颜色为根开一棵权值线段树,下标就是$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]旅行(树链剖分+线段树)的更多相关文章

  1. B20J_3231_[SDOI2014]旅行_树链剖分+线段树

    B20J_3231_[SDOI2014]旅行_树链剖分+线段树 题意: S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,城市信仰不同的宗教,为了方便,我们用不同的正整数代表各种宗教. S国 ...

  2. 洛谷P3313 [SDOI2014]旅行 题解 树链剖分+线段树动态开点

    题目链接:https://www.luogu.org/problem/P3313 这道题目就是树链剖分+线段树动态开点. 然后做这道题目之前我们先来看一道不考虑树链剖分之后完全相同的线段树动态开点的题 ...

  3. BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 )

    BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 ) 题意分析 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 ...

  4. BZOJ.1036 [ZJOI2008]树的统计Count ( 点权树链剖分 线段树维护和与最值)

    BZOJ.1036 [ZJOI2008]树的统计Count (树链剖分 线段树维护和与最值) 题意分析 (题目图片来自于 这里) 第一道树链剖分的题目,谈一下自己的理解. 树链剖分能解决的问题是,题目 ...

  5. BZOJ 3672[NOI2014]购票(树链剖分+线段树维护凸包+斜率优化) + BZOJ 2402 陶陶的难题II (树链剖分+线段树维护凸包+分数规划+斜率优化)

    前言 刚开始看着两道题感觉头皮发麻,后来看看题解,发现挺好理解,只是代码有点长. BZOJ 3672[NOI2014]购票 中文题面,题意略: BZOJ 3672[NOI2014]购票 设f(i)f( ...

  6. bzoj 4196 [Noi2015]软件包管理器 (树链剖分+线段树)

    4196: [Noi2015]软件包管理器 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 2852  Solved: 1668[Submit][Sta ...

  7. bzoj 2157: 旅游【树链剖分+线段树】

    裸的树链剖分+线段树 但是要注意一个地方--我WA了好几次才发现取完相反数之后max值和min值是要交换的-- #include<iostream> #include<cstdio& ...

  8. BZOJ 3589 动态树 (树链剖分+线段树)

    前言 众所周知,90%90\%90%的题目与解法毫无关系. 题意 有一棵有根树,两种操作.一种是子树内每一个点的权值加上一个同一个数,另一种是查询多条路径的并的点权之和. 分析 很容易看出是树链剖分+ ...

  9. 【BZOJ-2325】道馆之战 树链剖分 + 线段树

    2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 1153  Solved: 421[Submit][Statu ...

  10. 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树

    [BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...

随机推荐

  1. k-近邻算法(kNN)笔记

    #mat()函数可以将数组(array)转化为矩阵(matrix)# randMat = mat(random.rand(4,4))# 求逆矩阵:randMat.I# 存储逆矩阵:invRandMat ...

  2. Mac os下设置国内镜像加速站

    无法忍受国外pip 仓库的龟速地址,安利一波国内高速镜像地址... 首推阿里云 repository 马爸爸  I ❤ u $ vim ~/.pip/pip.conf 在config中做如下配置: [ ...

  3. 高并发大流量专题---11、Web服务器的负载均衡

    高并发大流量专题---11.Web服务器的负载均衡 一.总结 一句话总结: 推荐使用nginx七层(应用层)负载均衡的实现:配置那是相当的简单 http{ upstream cluster{ serv ...

  4. USB入门开发的八个问题&USB枚举『转』

    USB 基本知识 USB的重要关键字: 1.端点:位于USB设备或主机上的一个数据缓冲区,用来存放和发送USB的各种数据,每一个端点都有惟一的确定地址,有不同的传输特性(如输入端点.输出端点.配置端点 ...

  5. leetcode-解题记录 771. 宝石与石头

    题目: 给定字符串J 代表石头中宝石的类型,和字符串 S代表你拥有的石头. S 中每个字符代表了一种你拥有的石头的类型,你想知道你拥有的石头中有多少是宝石. J 中的字母不重复,J 和 S中的所有字符 ...

  6. 读取 appsettings.json

    Appsettings.json 配置: 个配置文件就是一个json文件,并且是严格的json文件,所有的属性都需要添加“”引号.下图是一个常规的代码示例: {"UrlString" ...

  7. 安装Elasticsearch5.4.0以及head,kibana插件

    可以在网盘中下载也可以去官网下载 网盘: Elasticsearch 地址:http://pan.baidu.com/s/1hrI0AFU elasticsearch-head  地址:http:// ...

  8. GET和POST的数据传递到底有何区别?

    1. GET和POST与数据如何传递没有关系 GET和POST是由HTTP协议定义的.在HTTP协议中,Method和Data(URL, Body, Header)是正交的两个概念,也就是说,使用哪个 ...

  9. android ndk 编译 libevent

    1. 下载 libevent 2.1.8 版本 https://github.com/libevent/libevent/releases/download/release-2.1.8-stable/ ...

  10. HTMLtr 标签的 valign 属性

    valign 属性规定表格行中内容的垂直对齐方式. <table width="100%" border="1"> <tr valign=&q ...