题目链接: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. 怎么得到scrollTop

    我们学习一个事件 :  页面滚动效果 window.onscroll = function() { 页面滚动语句  } 谷歌浏览器 和没有声明 DTD  <DOCTYPE     > : ...

  2. 复制功能 js

    示例: <input class="herf" type="text" v-model="herfUrl" readonly=&quo ...

  3. vue入门:实现图片点击切换

    1.实现功能 2.目录结构 3.代码 <!DOCTYPE html> <html lang="en"> <head> <meta char ...

  4. meclipse6.5破解

    package com.test.ssh.common;   import java.text.DecimalFormat; import java.text.NumberFormat; import ...

  5. LeetCode 中级 - 路径总和2(113)

    给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径. 说明: 叶子节点是指没有子节点的节点. 示例:给定如下二叉树,以及目标和 sum = 22, 5 / \ 4 8 ...

  6. 【SHOI2015】脑洞治疗仪(恶心的线段树,区间最大子段和)

    题目描述: 曾经发明了自动刷题机的发明家 SHTSC 又公开了他的新发明:脑洞治疗仪——一种可以治疗他因为发明而日益增大的脑洞的神秘装置. 为了简单起见,我们将大脑视作一个 01 序列.11代表这个位 ...

  7. canvas 制作表情包

    canvas 制作表情包 代码如下. <!DOCTYPE html> <html> <head> <title>表情制作</title> & ...

  8. Ajax异步交互

    一.简介 Ajax(Asynchronous JavaScript and XML).一般都写为Ajax. Ajax是与服务器交换数组并更新部分网页的艺术.最初的使用时2005中Google Sugg ...

  9. 模块importlib介绍

    importlib包的目的是双重的.一个是在Python源代码中提供import语句(以及扩展名为__import__()函数)的实现.这提供了可以移植到任何Python解释器的import的实现.这 ...

  10. MYSQL 版本5.7.24 sql_mode=only_full_group_by问题

    具体出错提示: [Err] 1055 - Expression #1 of ORDER BY clause is not in GROUP BY clause and contains nonaggr ...