题目链接: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. o'Reill的SVG精髓(第二版)学习笔记——第十章

    10.1 裁剪路径 创建SVG文档时,可以通过制定感兴趣区域的宽度和高度建立视口.这会变成默认的裁剪区域,任何绘制在该范围外部的部分都不会显示.你也可以使用<clipPath>元素来建立自 ...

  2. rm -f + 文件名+* 与 rm -f + 文件名* 的不同效果,大坑呀。

    rm -f catalina.2018-10-22.*    与*号间无空格 rm -f catalina.2018-10-22. *    :多了空格:

  3. oracle https://localhost:1158/em 无法打开

    解决办法一: 首先查看本机Oracle安装路径中 portlist.ini 文件里面的端口号是多少,例如我的就是5500. 那么在浏览器中输入的地址就是:https://localhost:5500/ ...

  4. P3818 小A和uim之大逃离 II(bfs,有条件的广搜)

    题目背景 话说上回……还是参见 https://www.luogu.org/problem/show?pid=1373 吧 小a和uim再次来到雨林中探险.突然一阵南风吹来,一片乌云从南部天边急涌过来 ...

  5. JQuery实现注册表单验证

    效果图如下: 注册页面HTML代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" &qu ...

  6. mysqldump备份与基于bin-log实现完全恢复

    MySQL数据库备份是一项非常重要的工作,mysql的备份主要分为逻辑备份和物理备份,同时,不同的生产环境要备份的策略也不会不同.下面先说一说备份时要考虑到的一些因素,然后再实际操作进行不同方式的数据 ...

  7. 【c学习-8】

    /*继承结构体*/ #include // 定义子结构体 struct date{ int year; int month; int day; }; //定义父结构体 struct student{ ...

  8. @staticmethod怎么用?

    早上起来写个小demo, 类中写了个方法, pycharm给这个方法加上了莫名其妙的波浪线, 对于一个有代码洁癖的人来说, 完全不能忍, 来看看为什么. 问题重现 pycharm的提示 上面说了, 这 ...

  9. dos命令操作数据库(上)

    1.cd到mysql安装目录bin目录: 2.输入id.用户名和密码: 3.查看数据库实例: 4.创建一个实例: 5.删除一个实例: 6.创建一个表: 7.删除一个表: 8.表结构: 9.修改表: 你 ...

  10. 3. 进程间通信IPC

    一.概念 IPC: 1)在linux环境中的每个进程各自有不同的用户地址空间.任何一个进程的全局变量在另一个进程中都看不到,所以进程和进程之间是不能相互访问. 2)如果进程间要交换数据必须通过内核,在 ...