题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3531

题意概述:
  给出一棵N个点的树,树上的每个结点有一个颜色和权值,支持以下四种操作:
  1.将点x的颜色改成c。
  2.将点x的权值给成w。
  3.询问x->y路径上和端点相同颜色的点的权值总和(端点颜色相同)。
  4.询问x->y路径上和端点相同颜色的点的权值最大值(端点颜色相同)。

分析:

  首先树链剖分,每条链开C棵维护每个颜色的线段树。动态开点。

  感觉没什么好说的......考试的时候灵光一闪就来了......之前还在YYlct之类的......

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<cctype>
using namespace std;
const int maxn=;
const int SIZE=; int N,Q,C[maxn],W[maxn];
map<int,int>rt[maxn];
struct edge{ int to,next; }E[maxn<<];
int first[maxn],np,dep[maxn],top[maxn],fa[maxn],son[maxn],sz[maxn],len[maxn];
int lc[SIZE],rc[SIZE],sum[SIZE],mx[SIZE],np2; void _scanf(int &x)
{
x=;
char ch=getchar();
while(ch<''||ch>'') ch=getchar();
while(ch>=''&&ch<='') x=x*+ch-'',ch=getchar();
}
void _scanf(char *s)
{
int cnt=;
char ch=getchar();
while(!isalpha(ch)) ch=getchar();
while(isalpha(ch)) s[cnt++]=ch,ch=getchar();
s[cnt]='\0';
}
int out_cnt,out[];
void _printf(int x)
{
out[++out_cnt]=x%,x/=;
while(x) out[++out_cnt]=x%,x/=;
while(out_cnt) putchar(''+out[out_cnt--]);
putchar('\n');
}
void add_edge(int u,int v){
E[++np]=(edge){v,first[u]};
first[u]=np;
}
void data_in()
{
_scanf(N);_scanf(Q);
for(int i=;i<=N;i++) _scanf(W[i]),_scanf(C[i]);
int x,y;
for(int i=;i<N;i++){
_scanf(x);_scanf(y);
add_edge(x,y); add_edge(y,x);
}
}
void DFS1(int i,int f,int d){
fa[i]=f,dep[i]=d,sz[i]=;
for(int p=first[i];p;p=E[p].next){
int j=E[p].to;
if(j==f) continue;
DFS1(j,i,d+);
sz[i]+=sz[j];
if(sz[j]>sz[son[i]]) son[i]=j;
}
}
void DFS2(int i,int f,int tp){
top[i]=tp,len[tp]++;
if(son[i]) DFS2(son[i],i,tp);
for(int p=first[i];p;p=E[p].next){
int j=E[p].to;
if(j==f||j==son[i]) continue;
DFS2(j,i,j);
}
}
int newnode(){
np2++,lc[np2]=rc[np2]=,sum[np2]=mx[np2]=;
return np2;
}
void pushup(int now){
mx[now]=max(mx[lc[now]],mx[rc[now]]);
sum[now]=sum[lc[now]]+sum[rc[now]];
}
void update(int &now,int L,int R,int pos,int v){
if(!now) now=newnode();
if(L==R){ sum[now]=mx[now]=v; return; }
int m=L+R>>;
if(pos<=m) update(lc[now],L,m,pos,v);
else update(rc[now],m+,R,pos,v);
pushup(now);
}
void build(int i,int f){
update(rt[top[i]][C[i]],,len[top[i]]-,dep[i]-dep[top[i]],W[i]);
for(int p=first[i];p;p=E[p].next){
if(E[p].to==f) continue;
build(E[p].to,i);
}
}
int query1(int now,int L,int R,int A,int B){
if(!now) return ;
if(A<=L&&R<=B) return sum[now];
int m=L+R>>;
if(B<=m) return query1(lc[now],L,m,A,B);
if(A>m) return query1(rc[now],m+,R,A,B);
return query1(lc[now],L,m,A,B)+query1(rc[now],m+,R,A,B);
}
int query2(int now,int L,int R,int A,int B){
if(!now) return ;
if(A<=L&&R<=B) return mx[now];
int m=L+R>>;
if(B<=m) return query2(lc[now],L,m,A,B);
if(A>m) return query2(rc[now],m+,R,A,B);
return max(query2(lc[now],L,m,A,B),query2(rc[now],m+,R,A,B));
}
int LCA(int x,int y){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
x=fa[top[x]];
}
return dep[x]<dep[y]?x:y;
}
int query_s(int x,int y,int c){
int re=;
while(top[x]!=top[y]){
re+=query1(rt[top[x]][c],,len[top[x]]-,,dep[x]-dep[top[x]]);
x=fa[top[x]];
}
re+=query1(rt[top[x]][c],,len[top[x]]-,dep[y]-dep[top[x]],dep[x]-dep[top[x]]);
return re;
}
int query_m(int x,int y,int c){
int re=;
while(top[x]!=top[y]){
re=max(re,query2(rt[top[x]][c],,len[top[x]]-,,dep[x]-dep[top[x]]));
x=fa[top[x]];
}
re=max(re,query2(rt[top[x]][c],,len[top[x]]-,dep[y]-dep[top[x]],dep[x]-dep[top[x]]));
return re;
}
void work()
{
DFS1(,,);
DFS2(,,);
build(,);
char op[];
int x,y,z,p,c,w,ans;
for(int i=;i<=Q;i++){
_scanf(op);
if(op[]=='C'&&op[]=='C'){
_scanf(x);_scanf(c);
update(rt[top[x]][C[x]],,len[top[x]]-,dep[x]-dep[top[x]],);
update(rt[top[x]][C[x]=c],,len[top[x]]-,dep[x]-dep[top[x]],W[x]);
}
else if(op[]=='C'&&op[]=='W'){
_scanf(x);_scanf(w);
update(rt[top[x]][C[x]],,len[top[x]]-,dep[x]-dep[top[x]],W[x]=w);
}
else if(op[]=='S'){
_scanf(x);_scanf(y);
z=LCA(x,y);
_printf(query_s(x,z,C[x])+query_s(y,z,C[x])-(C[z]==C[x]?W[z]:));
}
else if(op[]=='M'){
_scanf(x);_scanf(y);
z=LCA(x,y);
_printf(max(query_m(x,z,C[x]),query_m(y,z,C[x])));
}
}
}
int main()
{
data_in();
work();
return ;
}
 

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. caffe convert mxnet

    https://github.com/apache/incubator-mxnet/tree/430ea7bfbbda67d993996d81c7fd44d3a20ef846/tools/caffe_ ...

  2. 前端路由原理及vue-router介绍

    前端路由原理本质就是监听 URL 的变化,然后匹配路由规则,显示相应的页面,并且无须刷新.目前单页面使用的路由就只有两种实现方式 hash history www.test.com/##/ 就是 Ha ...

  3. 使用dva框架的总结

    最近的项目是react+dva+atd+webpack的一个后台项目,刚接触dva就感觉很喜欢,很简洁用着很爽. 关于使用redux中的一些问题 1.文件切换问题. redux的项目通常哟啊分为red ...

  4. 【TOJ 1545】Hurdles of 110m(动态规划)

    描述 In the year 2008, the 29th Olympic Games will be held in Beijing. This will signify the prosperit ...

  5. OCCI开发环境搭建(Ubuntu)

    OCCI开放包(下载与服务器版本相同的开发包, 这用的是12.1.0.2): instantclient-basic-linux.x64-12.1.0.2.0.zip instantclient-sd ...

  6. PHP中对字符串的一些操作

    php中判断字符串在另一个字符串中是否存在(strpos): if(strpos('www.baidu.com', 'www') !== false){ // 存在 }else{ // 不存在 } p ...

  7. MySQL innodb表使用表空间物理文件复制或迁移表

    MySQL InnoDB引擎的表通过拷贝物理文件来进行单表或指定表的复制,可以想到多种方式,今天测试其中2种: 将innodb引擎的表修改为Myisam引擎,然后拷贝物理文件 直接拷贝innodb的表 ...

  8. rails小技巧之分组查询统计并去重

    分组查询并统计 SpecialGroup.group(:special_type).count select special_type,count(*) from special_groups gro ...

  9. ubuntu64位运行32位程序

    sudo dpkg --add-architecture i386 sudo apt install libc6:i386 转:https://blog.csdn.net/zoomdy/article ...

  10. 004---Python基本数据类型--元祖

    元祖 .caret, .dropup > .btn > .caret { border-top-color: #000 !important; } .label { border: 1px ...