[bzoj3531][Sdoi2014][旅行] (主席树+树链剖分)
Description
S国有N个城市,编号从1到N。城市间用N-1条双向道路连接,满足
从一个城市出发可以到达其它所有城市。每个城市信仰不同的宗教,如飞天面条神教、隐形独角兽教、绝地教都是常见的信仰。为了方便,我们用不同的正整数代表各种宗教, S国的居民常常旅行。旅行时他们总会走最短路,并且为了避免麻烦,只在信仰和他们相同的城市留宿。当然旅程的终点也是信仰与他相同的城市。S国政府为每个城市标定了不同的旅行评级,旅行者们常会记下途中(包括起点和终点)留宿过的城市的评级总和或最大值。
在S国的历史上常会发生以下几种事件:
”CC x c”:城市x的居民全体改信了c教;
”CW x w”:城市x的评级调整为w;
”QS x y”:一位旅行者从城市x出发,到城市y,并记下了途中留宿过的城市的评级总和;
”QM x y”:一位旅行者从城市x出发,到城市y,并记下了途中留宿过
的城市的评级最大值。
由于年代久远,旅行者记下的数字已经遗失了,但记录开始之前每座城市的信仰与评级,还有事件记录本身是完好的。请根据这些信息,还原旅行者记下的数字。 为了方便,我们认为事件之间的间隔足够长,以致在任意一次旅行中,所有城市的评级和信仰保持不变。
Input
输入的第一行包含整数N,Q依次表示城市数和事件数。
接下来N行,第i+l行两个整数Wi,Ci依次表示记录开始之前,城市i的
评级和信仰。
接下来N-1行每行两个整数x,y表示一条双向道路。
接下来Q行,每行一个操作,格式如上所述。
Output
对每个QS和QM事件,输出一行,表示旅行者记下的数字。
Sample Input
QS
CC
QS
CW
QS
QM
Sample Output
HINT
N,Q < =10^5 , C < =10^5
数据保证对所有QS和QM事件,起点和终点城市的信仰相同;在任意时
刻,城市的评级总是不大于10^4的正整数,且宗教值不大于C。
Solution
水题
用主席树做一做就好
#include <stdio.h>
#include <string.h>
#define RG register
#define N 100010
#define dmax(a,b) ((a)>(b)?(a):(b))
template<class Type> inline void R(RG Type &x) {
RG int c=getchar();for(;c<48||c>57;c=getchar());
for(x=0;c>47&&c<58;x=(x<<1)+(x<<3)+c-48,c=getchar()); }
bool vis[N];int n,q,w[N],c[N],tim,fa[N],dep[N],sz[N],lef[N],top[N],hso[N],tot,root[N];
struct Pt {
int v; Pt *nt; }*fi[N],me[N<<1],*tp=me;
struct Ch {
int ls,rs,mx,su; }tr[N*40];
inline void link(RG int x,RG int y) {
*++tp=(Pt){y,fi[x]},fi[x]=tp;
*++tp=(Pt){x,fi[y]},fi[y]=tp; }
void dfsi(RG int x){
vis[x]=sz[x]=1;
for(RG Pt *it=fi[x];it;it=it->nt)
if(!vis[it->v])
dep[it->v]=dep[x]+1,
fa[it->v]=x,
dfsi(it->v),
sz[x]+=sz[it->v],
hso[x]=sz[it->v]>sz[hso[x]]?it->v:hso[x];
}
void dfsm(RG int x){
vis[x]=0;
top[x]=x==hso[fa[x]]?top[fa[x]]:x;
lef[x]=++tim;
if(hso[x]){
dfsm(hso[x]);
for(RG Pt *it=fi[x];it;it=it->nt)
if(vis[it->v])
dfsm(it->v);
}
}
inline int lca(RG int x,RG int y){
while(top[x]^top[y])
dep[top[x]]>dep[top[y]]?
x=fa[top[x]]:
y=fa[top[y]];
return dep[x]<dep[y]?x:y;
}
inline void Pu(RG int pr) {
tr[pr].mx=dmax(tr[tr[pr].ls].mx,tr[tr[pr].rs].mx);
tr[pr].su=tr[tr[pr].ls].su+tr[tr[pr].rs].su; }
void modify(RG int &pr,RG int x,RG int y,RG int po,RG int nu){
if(!pr)pr=++tot;
if(!(x^y)) {tr[pr].mx=tr[pr].su=nu; return; }
RG int mid=x+y>>1;
if(po<=mid)modify(tr[pr].ls,x,mid,po,nu);
else modify(tr[pr].rs,mid+1,y,po,nu);
Pu(pr);
}
int qmx(RG int pr,RG int x,RG int y,RG int u,RG int v){
if(!pr)return 0;
if(x==u&&y==v)return tr[pr].mx;
RG int mid=x+y>>1;
if(v<=mid)return qmx(tr[pr].ls,x,mid,u,v);
if(u>mid)return qmx(tr[pr].rs,mid+1,y,u,v);
return dmax(qmx(tr[pr].ls,x,mid,u,mid),qmx(tr[pr].rs,mid+1,y,mid+1,v));
}
int qsm(RG int pr,RG int x,RG int y,RG int u,RG int v){
if(!pr)return 0;
if(x==u&&y==v)return tr[pr].su;
RG int mid=x+y>>1;
if(v<=mid)return qsm(tr[pr].ls,x,mid,u,v);
if(u>mid)return qsm(tr[pr].rs,mid+1,y,u,v);
return qsm(tr[pr].ls,x,mid,u,mid)+qsm(tr[pr].rs,mid+1,y,mid+1,v);
}
inline int solvem(RG int col,RG int x,RG int f){
int re=0;
while(top[x]^top[f])
re=dmax(re,qmx(root[col],1,n,lef[top[x]],lef[x])),x=fa[top[x]];
re=dmax(re,qmx(root[col],1,n,lef[f],lef[x]));
return re;
}
inline int solves(int col,int x,int f){
int re=0;
while(top[x]^top[f])
re+=qsm(root[col],1,n,lef[top[x]],lef[x]),x=fa[top[x]];
re+=qsm(root[col],1,n,lef[f],lef[x]);
return re;
}
int main(){
RG char si[10];R(n),R(q);
for(RG int i=1;i<=n;i++)R(w[i]),R(c[i]);
for(RG int i=1,x,y;i<n;i++)R(x),R(y),link(x,y);
dfsi(1),dfsm(1);
for(RG int i=1;i<=n;i++)modify(root[c[i]],1,n,lef[i],w[i]);
for(int x,y,t,tmp;q;q--){
scanf("%s",si),R(x),R(y);
if(si[0]=='C'&&si[1]=='C')
modify(root[c[x]],1,n,lef[x],0),
c[x]=y,
modify(root[c[x]],1,n,lef[x],w[x]);
if(si[0]=='C'&&si[1]=='W')
modify(root[c[x]],1,n,lef[x],y),w[x]=y;
if(si[0]=='Q'&&si[1]=='S')
t=lca(x,y),tmp=solves(c[x],x,t)+solves(c[x],y,t),c[x]==c[t]?tmp-=w[t]:1,printf("%d\n",tmp);
if(si[0]=='Q'&&si[1]=='M')
t=lca(x,y),printf("%d\n",dmax(solvem(c[x],x,t),solvem(c[x],y,t)));
}
return 0;
}
[bzoj3531][Sdoi2014][旅行] (主席树+树链剖分)的更多相关文章
- BZOJ3531 SDOI2014 旅行 - 树链剖分,主席树
题意:给定一棵树,树上每个点有权值和类型.支持:修改某个点的类型:修改某个点的权值:询问某条链上某个类型的点的和/最大值.点数/类型数/询问数<=100000. 分析: 树链剖分,对每个类型的点 ...
- BZOJ3531 [Sdoi2014]旅行 树链剖分 线段树
原文链接:http://www.cnblogs.com/zhouzhendong/p/8080189.html 题目传送门 - BZOJ3531 题意概括 一棵树,n个节点,每一个节点两个值,一个颜色 ...
- BZOJ3531[Sdoi2014]旅行——树链剖分+线段树
题目描述 S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰.为了方便,我们 ...
- BZOJ3531:[SDOI2014]旅行(树链剖分)
Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足 从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰 ...
- 2018.07.24 bzoj3531: [Sdoi2014]旅行(树链剖分+动态开点)
传送门 树链剖分. 如何维护? 如果颜色少直接每种颜色一颗线段树走人. 但这题颜色数量不大于1e5" role="presentation" style="po ...
- 【块状树】【树链剖分】【线段树】bzoj3531 [Sdoi2014]旅行
离线后以宗教为第一关键字,操作时间为第二关键字排序. <法一>块状树,线下ac,线上tle…… #include<cstdio> #include<cmath> # ...
- 线段树&数链剖分
傻逼线段树,傻逼数剖 线段树 定义: 线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点. 使用线段树可以快速的查找某一个节点在若干条线段中出现 ...
- Bzoj3531: [Sdoi2014]旅行
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1698 Solved: 758 Description S国有N个城市,编号从1到N.城市间用N-1 ...
- bzoj3531: [Sdoi2014]旅行 (树链剖分 && 动态开点线段树)
感觉动态开点线段树空间复杂度好优秀呀 树剖裸题 把每个宗教都开一颗线段树就可以了 但是我一直TLE 然后调了一个小时 为什么呢 因为我 #define max(x, y) (x > y ? x ...
随机推荐
- 压力测试之jmeter使用
我很早之前就会使用jmeter,一直以为压力测试很简单,知道真正去做才明白,真正的压力测试并不只是会用jmeter而已.我现在才明白:会工具并不等同于会压力测试.对于压力测试需要补充的知识还有很多.. ...
- ROS学习笔记八:基于Qt搭建ROS开发环境
1 前言 本文介绍一种Qt下进行ROS开发的完美方案,使用的是ros-industrial的Levi-Armstrong在2015年12月开发的一个Qt插件ros_qtc_plugin,这个插件使得Q ...
- Race to 1 Again LightOJ - 1038
Race to 1 Again LightOJ - 1038 题意:有一个数字D,每次把D变为它的一个因数(变到所有因数的概率相等,可能是本身),变到1后停止.求对于某个初始的D变到1的期望步数. x ...
- 事件模型的介绍与Button的ActionListener
事件监听: 这是个很重要的概念,也是个很重要的模型,vb,vc都是这样用,甚至后面学的web框架也在用. 现在我们可以做很多按钮了吧,但是我们的按钮按它是没反应的,现在我们来看看怎么样才能让它有 ...
- ES6知识点汇总
MDN镇楼: https://developer.mozilla.org/zh-CN/ 1.ES6新添加数据类型:symbol ----------- https://developer.moz ...
- node入门(一)——安装
node可以让我们用js写服务器.此外还可以用来前端自动化开发,它找到特定服务要使用的包,然后下载.安装.管理. 首先安装node,进入官网下载需要的node版本,然后一键式傻瓜安装.(我的环境是wi ...
- web api 解决Ajax请求跨域问题
前端ajax请求接口时,经常出现跨域问题,当然了解决方法有很多种,比如: http://www.jb51.net/article/68424.htm 我本人恰好前后端都会一点,所以直接在接口端处理. ...
- 构建一个.net的干货类库,以便于快速的开发 - 验证码
一个验证码对于一个网站的作用不言而喻,而随着技术的发展验证码的种类也开始多了起来,发展至今很多网站已经不再使用一种验证码,为满足需求程序猿就要写很多的方法来适应需求,今天我就来介绍我之前收集到的验证码 ...
- Java 线程是什么-渐入佳境
线程:(一)什么是线程 管哥说:程序中有多个执行流就叫多线程.多线程是多任务的一种特别的形式.好处:单个程序可以创建多个并发执行的程序来完成各自的任务.多线程能满足程序员编写高效率的程序来达到充分利用 ...
- [BZOJ1088][SCOI2005]扫雷Mine DP
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1088 记录下每一个格子对应左边格子放的雷的情况,然后dp转移就好了. #include&l ...