题目大意 :
有 n 个城市连成一棵树, 每个城市有两个关键字, 一个是该城市的宗教, 另一个是城市的评级;
旅行者要在城市间旅行, 他只会在和自己宗教相同的城市留宿;
维护四个树上操作 {
1. “CC x c“ :城市 x 的居民全体改信了 c 教;
2. “CW x w“ :城市 x 的评级调整为 w;
3. “QS x y“ :一位旅行者从城市 x 出发,到城市 y,并记下了途中留宿过的城市的评级总和;
4. “QM x y“:一位旅行者从城市 x 出发,到城市 y ,并记下了途中留宿过的城市的评级最大值;
}
(旅行者信的教和旅行的终点相同;

树剖+线段树 : 如果对每种宗教都开一颗线段树, 内存爆炸 -------> 考虑动态开点

动态开点 {
在这道题中, 可以考虑给每一种宗教开一个线段树, 但一开始不需要开满;
对于每一个第一次出现的宗教或者一个宗教里的一个新城市, 都把他当做一个新节点;
对于单次操作 时间复杂度和空间复杂度都是 O(log n) , 因为对于一种宗教最多有n个节点, 在线段树里找到一个节点最多 logn+1 次;
}

代码如下 :

 //Author : 15owzLy1
//luogu3313.cpp
//2018 12 09 14:24:30
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define INF 2100000000
typedef long long ll;
typedef double db;
template<typename T>inline void read(T &_) {
_=;int __=;char ___=getchar();
while(___<''||___>'')__|=(___=='-'),___=getchar();
while(___>=''&&___<='')_=(_<<)+(_<<)+(___^),___=getchar();
_=__?-_:_;
} const int N = (int)1e5+;
struct edge {
int next, to;
}edge[N<<];
int head[N], cnt=, c[N], w[N];
int n, q, hson[N], size[N], dfn[N], front[N], dep[N], fa[N]; class Segment_Tree {
private :
struct node {
int sum, max, l, r;
#define t a[rt]
#define lson a[a[rt].l]
#define rson a[a[rt].r]
}a[N*];
int cnt;
inline void push_up(int rt) {
t.sum=lson.sum+rson.sum;
t.max=std::max(lson.max, rson.max);
}
public :
int root[N];
void update(int &rt, int del, int tl, int tr, int pos) {
if(!rt) rt=++cnt;
if(tl==tr) { t.max=t.sum=del; return ; }
int mid=(tl+tr)>>;
if(mid>=pos) update(t.l, del, tl, mid, pos);
else update(t.r, del, mid+, tr, pos);
push_up(rt);
}
void remove(int &rt, int tl, int tr, int pos) {
if(tl==tr) { rt=t.sum=t.max=; return ; }
int mid=(tl+tr)>>;
if(mid>=pos) remove(t.l, tl, mid, pos);
else remove(t.r, mid+, tr, pos);
push_up(rt);
}
int query_sum(int rt, int l, int r, int tl, int tr) {
if(l<=tl&&tr<=r) return t.sum;
int mid=(tl+tr)>>, ret=;
if(mid>=l) ret+=query_sum(t.l, l, r, tl, mid);
if(mid<r) ret+=query_sum(t.r, l, r, mid+, tr);
return ret;
}
int query_max(int rt, int l, int r, int tl, int tr) {
if(l<=tl&&tr<=r) return t.max;
int mid=(tl+tr)>>, ret=;
if(mid>=l) ret=std::max(ret, query_max(t.l, l, r, tl, mid));
if(mid<r) ret=std::max(ret, query_max(t.r, l, r, mid+, tr));
return ret;
}
}T; inline void jb(int u, int v) {
edge[++cnt].to=v;
edge[cnt].next=head[u];
head[u]=cnt;
} void get_hson(int u) {
size[u]=;
for(int i=head[u];i;i=edge[i].next) {
int v=edge[i].to;
if(v==fa[u]) continue;
fa[v]=u, dep[v]=dep[u]+;
get_hson(v);
size[u]+=size[v];
if(size[v]>=size[hson[u]]) hson[u]=v;
}
} void get_front(int u, int father) {
dfn[u]=++dfn[], front[u]=father;
if(hson[u]) get_front(hson[u], father);
for(int i=head[u];i;i=edge[i].next) {
int v=edge[i].to;
if(v==fa[u]||v==hson[u]) continue;
get_front(v, v);
}
} inline int query_sum(int u, int v) {
int ret=, cl=c[v];
while(front[u]!=front[v]) {
if(dep[front[u]]>dep[front[v]]) std::swap(u, v);
ret+=T.query_sum(T.root[cl], dfn[front[v]], dfn[v], , n);
v=fa[front[v]];
}
if(dep[u]>dep[v]) std::swap(u, v);
ret+=T.query_sum(T.root[cl], dfn[u], dfn[v], , n);
return ret;
} inline int query_max(int u, int v) {
int ret=, cl=c[v];
while(front[u]!=front[v]) {
if(dep[front[u]]>dep[front[v]]) std::swap(u, v);
ret=std::max(ret, T.query_max(T.root[cl], dfn[front[v]], dfn[v], , n));
v=fa[front[v]];
}
if(dep[u]>dep[v]) std::swap(u, v);
ret=std::max(ret, T.query_max(T.root[cl], dfn[u], dfn[v], , n));
return ret;
} int main() {
#ifndef ONLINE_JUDGE
freopen("luogu3313.in","r",stdin);
freopen("luogu3313.out","w",stdout);
#endif
char opt[];
int x, y;
read(n), read(q);
for(int i=;i<=n;i++) read(w[i]), read(c[i]);
for(int i=;i<n;i++) read(x), read(y), jb(x, y), jb(y, x);
get_hson(); get_front(, );
for(int i=;i<=n;i++)
T.update(T.root[c[i]], w[i], , n, dfn[i]); while(q--) {
scanf("%s", opt);
read(x), read(y);
if(opt[]=='C') {
//change C change W
if(opt[]=='C') {
T.remove(T.root[c[x]], , n, dfn[x]);
c[x]=y;
T.update(T.root[c[x]], w[x], , n, dfn[x]);
}
else T.update(T.root[c[x]], y, , n, dfn[x]), w[x]=y;
}
else {
//query S query W
if(opt[]=='S') printf("%d\n", query_sum(x, y));
else printf("%d\n", query_max(x, y));
}
}
return ;
}

「luogu3313」[SDOI2014] 旅行的更多相关文章

  1. Loj #3057. 「HNOI2019」校园旅行

    Loj #3057. 「HNOI2019」校园旅行 某学校的每个建筑都有一个独特的编号.一天你在校园里无聊,决定在校园内随意地漫步. 你已经在校园里呆过一段时间,对校园内每个建筑的编号非常熟悉,于是你 ...

  2. @loj - 2987@ 「CTSC2016」时空旅行

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 2045 年,人类的技术突飞猛进,已经找到了进行时空旅行的方法. ...

  3. LOJ 3057 「HNOI2019」校园旅行——BFS+图等价转化

    题目:https://loj.ac/problem/3057 想令 b[ i ][ j ] 表示两点是否可行,从可行的点对扩展.但不知道顺序,所以写了卡时间做数次 m2 迭代的算法,就是每次遍历所有不 ...

  4. 「loj3057」「hnoi2019」校园旅行

    题目 一个n个点m条边的无向图,每个点有0 / 1 的标号; 有q个询问,每次询问(u,v)直接是否存在回文路径(可以经过重复的点和边); $1 \le n \le 5 \times 10^3  , ...

  5. 【LOJ2604】「NOIP2012」开车旅行

    [题目链接] [点击打开链接] [题目大意] 从西到东的坐标轴\([1,n]\)上有\(n\)个海拔互不相同的城市,每两个城市之间的距离定义为\(dis(i,j)=|h_i-h_j|\) 小\(A\) ...

  6. 「NOIP2012」开车旅行

    传送门 Luogu 解题思路 第一步预处理每个点后面的最近点和次近点,然后就是模拟题意. 但是如果就这么搞是 \(O(N^2)\) 的,不过可以过70分,考场上也已经比较可观了. 考虑优化. 预处理最 ...

  7. 「JSOI2013」旅行时的困惑

    「JSOI2013」旅行时的困惑 传送门 由于我们的图不仅是一个 \(\text{DAG}\) 而且在形态上还是一棵树,也就是说我们为了实现节点之间互相可达,就必须把每条边都覆盖一次,因为两个点之间的 ...

  8. 「JSOI2010」旅行

    「JSOI2010」旅行 传送门 比较妙的一道 \(\text{DP}\) 题,思维瓶颈应该就是如何确定状态. 首先将边按边权排序. 如果我们用 \(01\) 串来表示 \(m\) 条边是否在路径上, ...

  9. 「案例」让房东在 Airbnb 上展示他们的热情好客

    如何才能让房东准确的描述自己的房源,如何才能让房东充分的展示自己的房源.Airbnb 在这次更新里尝试去解决了这两个问题,让我们跟随作者的文笔去了解一下整个项目的经过. 关于本文 原文作者:Cecil ...

随机推荐

  1. 【Git】+安装+使用+配置

    Git安装及使用: https://www.cnblogs.com/ximiaomiao/p/7140456.html Git下载地址: http://git-scm.com/download/win ...

  2. c++面经积累<2>

    4.类成员初始化方式:列表初始化和赋值初始化 赋值初始化通过在函数体内进行赋值,列表初始化,在构造函数后面加上冒号,使用初始化列表进行初始化.在函数体内进行初始化,是在所有的数据成员被分配内存空间后进 ...

  3. java中内存分配

    java程序运行时内存分配详解  一. 基本概念 每运行一个java程序会产生一个java进程,每个java进程可能包含一个或者多个线程,每一个Java进程对应唯一一个JVM实例,每一个JVM实例唯一 ...

  4. vue.js实战——vue元素复用

    Vue在渲染元素时,出于效率考虑,会尽可能地复用已有的元素而非重新渲染,例: <!DOCTYPE html> <html lang="en"> <he ...

  5. Shell命令-文件及目录操作之ls、cd

    文件及目录操作 - ls.cd 1.ls:列出目录的内容及其内容属性信息 ls命令的功能说明 ls命令用于列出目录的内容及其内容属性信息. ls命令的语法格式 ls [OPTION]... [FILE ...

  6. Python——设计模式——单例模式

    一个类始终只有一个实例 当你第一次实例化这个类的时候,就创建一个实例化得对象 当你之后再来实例化的时候,就用之前创建的对象 class A: __instance = False def __ini_ ...

  7. jsp篇 之 基本概念

    Jsp概念: 1.jsp是什么 jsp全称Java Server Pages,是一种[动态网页开发技术]. .html文件是静态页面 .jsp 文件是动态页面 jsp页面允许我们在html代码中[嵌入 ...

  8. linux服务器间文件夹拷贝

    要求,在A机器执行脚本,把A机器的某个目录文件拷贝到B机器. 第一版ftp实现: 1.A 机器先安装 ftp 客户端 $ sudo yum install ftp 2.B机器安装ftp服务端 $ su ...

  9. 百度在职 iOS 架构师的成长笔记,送给还在迷茫的你!

    前言 我们经常在网上会看到这样的文章,你的同龄人正在如何如何.......这是典型的贩卖焦虑的文章.的确,现阶段,刚毕业几年的年轻人,面临车,房子等,有时候压力挺大的. 但你过度焦虑的话,每天生活在恐 ...

  10. 20165232 实现pwd

    20165232 实现mypwd 题目要求 学习pwd命令 研究pwd实现需要的系统调用(man -k; grep),写出伪代码 实现mypwd 测试mypwd 学习pwd命令 用man pwd 查看 ...