传送门

解题思路

  以每个颜色为根开一棵权值线段树,下标就是$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. linux系统下jdk安装配置

    1.有jdk包(linux版) 2.放到linux系统下 3.建议在usr下新建jdk目录之后将jdk文件放到该目录下 3.配置系统信息   /etc/profile 需要配置的信息如下:#set j ...

  2. SPOJ - FTOUR2 (点分治+树状数组)

    题目:https://vjudge.net/contest/307753#problem/I 题意:有一颗树,上面有白色黑色点,每个点上有一个权值,权值可以为负,现在我要求一条路径,权值和最大,这条路 ...

  3. 【Java架构:持续交付】一篇文章搞掂:Jenkins

    一.安装 1.使用yum本地安装 1.1.使用yum安装JDK a.检查系统是否有安装open-jdk rpm -qa |grep java rpm -qa |grep jdk rpm -qa |gr ...

  4. django-admin.py和manage.py的用法

    [简介] django-admin.py是Django的一个用于管理任务的命令行工具.本文将描述它的大概用法. 另外,在每一个Django project中都会有一个manage.py.manage. ...

  5. (转)springboot应用启动原理(一) 将启动脚本嵌入jar

    转:https://segmentfault.com/a/1190000013489340 Spring Boot Takes an opinionated view of building prod ...

  6. 踩坑记之字体图标在webpack中

    首先介绍一个还不错的字体图标库: font-awesome 是在发现bootstrap在npm下载后没有font包以后重新找的字体库,内容还挺丰富的,好像还有动态图,感兴趣的可以看一下 我的环境是we ...

  7. idea中git回退远程仓库版本

    工作中遇到,代码已提交并已提交到远程仓库,现需要回退到之前版本,记录如下: 记录当前版本的版本号和需要回退到版本的版本号. current version:85e7f32dfe421c5892a4e2 ...

  8. 配送单MYSQL ,一点都不机智

    这是配送单制作,后面修改了下表 . 写的太乱. 不过也不想去修改了. 放在这里了.反正还能用. 不然就坑爹了. 以后写好一点. 这都是些神马, 太难受了. /* 配送单制作,缺少商品规格,以及库存查询 ...

  9. fiddler接口知识

    1. 访问接口时经常会出现乱码的情况,需要fiddler解码操作 2.域名过滤

  10. Cocos2d-x之事件处理机制

    |   版权声明:本文为博主原创文章,未经博主允许不得转载. 事件处理机制分为单点触屏,多点触屏,加速度事件,键盘事件和鼠标事件.在现在的智能手机中,触屏的应用比较的广泛,尤其是多点触屏事件的技术,使 ...