P3313 [SDOI2014]旅行
树链剖分+动态线段树(并不是lct)
显然的,我们对于每一个宗教都要维护一个线段树。
(那么空间不是爆炸了吗)
在这里引入:动态开点线段树
就是需要的点开起来,不需要的就不开。
其他地方和正常的线段树差不多
这样可以省下一堆空间。
code:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cctype>
#include<queue>
#define re register
using namespace std;
template <typename T> inline T min(T &a,T &b) {return a<b ?a:b;}
template <typename T> inline T max(T &a,T &b) {return a>b ?a:b;}
template <typename T> inline void read(T &x){
char c=getchar(); x=; bool f=;
while(!isdigit(c)) f= !f||c=='-' ? :,c=getchar();
while(isdigit(c)) x=(x<<)+(x<<)+(c^),c=getchar();
x= f ? x:-x;
}
template <typename T> inline void output(T x){
if(!x) {putchar(); return ;}
if(x<) putchar('-'),x=-x;
int wt[],l=;
while(x) wt[++l]=x%,x/=;
while(l) putchar(wt[l--]+);
}
typedef int arr[];
struct data{ //结构体存点
int l,r,mxd,sum;
void clear() {l=r=mxd=sum=;}
}a[]; //尽量开大
queue <int> lit;
int n,m,cnt,tot,u;
arr d,fa,siz,bgs,tp,val,sp,id,hd,ed,rt;
int nxt[],poi[];
inline void add_(int x,int y){
nxt[ed[x]]=++cnt; hd[x]= hd[x] ? hd[x]:cnt;
ed[x]=cnt; poi[cnt]=y;
}
inline void modify(int &o,int l,int r,int x,int v){ //引用地址便于修改
if(!o){
if(!lit.empty()) o=lit.front(),lit.pop(); //内存池节省空间
else o=++u;
}
if(l==r) {a[o].sum=a[o].mxd=v; return;}
int mid=l+((r-l)>>);
if(x<=mid) modify(a[o].l,l,mid,x,v);
else modify(a[o].r,mid+,r,x,v);
a[o].sum=a[a[o].l].sum+a[a[o].r].sum;
a[o].mxd=max(a[a[o].l].mxd,a[a[o].r].mxd);
}
inline void remov(int &o,int l,int r,int x){
if(l==r) {a[o].clear(); lit.push(o),o=; return;}
int mid=l+((r-l)>>);
if(x<=mid) remov(a[o].l,l,mid,x);
else remov(a[o].r,mid+,r,x);
a[o].sum=a[a[o].l].sum+a[a[o].r].sum;
a[o].mxd=max(a[a[o].l].mxd,a[a[o].r].mxd);
if(!a[o].l&&!a[o].r) a[o].clear(),lit.push(o),o=; //左右子树都空->该点为空->删掉
}
inline int query1(int o,int l,int r,int x1,int x2){
if(!o) return ; //注意空树要跳出
if(x1<=l&&r<=x2) return a[o].sum;
int mid=l+((r-l)>>),res=;
if(x1<=mid) res+=query1(a[o].l,l,mid,x1,x2);
if(x2>mid) res+=query1(a[o].r,mid+,r,x1,x2);
return res;
}
inline int query2(int o,int l,int r,int x1,int x2){
if(!o) return ;
if(x1<=l&&r<=x2) return a[o].mxd;
int mid=l+((r-l)>>),res=;
if(x1<=mid) res=max(res,query2(a[o].l,l,mid,x1,x2));
if(x2>mid) res=max(res,query2(a[o].r,mid+,r,x1,x2));
return res;
}
inline void dfs1(int x,int _fa){
d[x]=d[_fa]+,fa[x]=_fa,siz[x]=;
for(int i=hd[x];i;i=nxt[i])
if(poi[i]!=_fa){
dfs1(poi[i],x);
siz[x]+=siz[poi[i]];
if(siz[bgs[x]]<siz[poi[i]]) bgs[x]=poi[i];
}
}
inline void dfs2(int x,int _top){
id[x]=++tot,tp[x]=_top;
if(siz[x]==) return;
dfs2(bgs[x],_top);
for(int i=hd[x];i;i=nxt[i])
if(poi[i]!=fa[x]&&poi[i]!=bgs[x])
dfs2(poi[i],poi[i]);
}
inline int ask1(int x,int y){
int col=val[x],res=;
while(tp[x]!=tp[y]){
if(d[tp[x]]<d[tp[y]]) swap(x,y);
res+=query1(rt[col],,n,id[tp[x]],id[x]);
x=fa[tp[x]];
}if(d[x]>d[y]) swap(x,y);
return res+query1(rt[col],,n,id[x],id[y]);
}
inline int ask2(int x,int y){
int col=val[x],res=;
while(tp[x]!=tp[y]){
if(d[tp[x]]<d[tp[y]]) swap(x,y);
res=max(res,query2(rt[col],,n,id[tp[x]],id[x]));
x=fa[tp[x]];
}if(d[x]>d[y]) swap(x,y);
return max(res,query2(rt[col],,n,id[x],id[y]));
}
//------树剖基础操作--------
inline void change1(int x,int v){
remov(rt[val[x]],,n,id[x]);
modify(rt[val[x]=v],,n,id[x],sp[x]);
}//宗教改变:从原来那棵树删掉该点,再加到新树上
inline void change2(int x,int v){
modify(rt[val[x]],,n,id[x],sp[x]=v);
}//评价改变:直接修改
int main(){
read(n),read(m); int q1,q2; char opt[];
for(re int i=;i<=n;++i) read(sp[i]),read(val[i]);
for(re int i=;i<n;++i) read(q1),read(q2),add_(q1,q2),add_(q2,q1);
dfs1(,); dfs2(,);
for(re int i=;i<=n;++i) modify(rt[val[i]],,n,id[i],sp[i]);
for(re int i=;i<=m;++i){
scanf("%s",opt); read(q1),read(q2);
if(opt[]=='C'){
if(opt[]=='C') change1(q1,q2);
else change2(q1,q2);
}else{
if(opt[]=='S') output(ask1(q1,q2));
else output(ask2(q1,q2));
putchar('\n');
}
}return ;
}
P3313 [SDOI2014]旅行的更多相关文章
- [luogu P3313] [SDOI2014]旅行
[luogu P3313] [SDOI2014]旅行 题目描述 S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神 ...
- 洛谷 P3313 [SDOI2014]旅行 解题报告
P3313 [SDOI2014]旅行 题目描述 S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教 ...
- P3313 [SDOI2014]旅行——树链剖分+线段树(动态开点?)
P3313 [SDOI2014]旅行 一棵树,其中的点分类,点有权值,在一条链上找到一类点中的最大值或总和: 树链剖分把树变成链: 把每个宗教单开一个线段树,维护区间总和和最大值: 宗教很多,需要动态 ...
- 洛谷 P3313 [SDOI2014]旅行
题目描述 S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰. 为了方便,我 ...
- 洛谷P3313 [SDOI2014]旅行 题解 树链剖分+线段树动态开点
题目链接:https://www.luogu.org/problem/P3313 这道题目就是树链剖分+线段树动态开点. 然后做这道题目之前我们先来看一道不考虑树链剖分之后完全相同的线段树动态开点的题 ...
- 洛谷P3313 [SDOI2014]旅行(树链剖分 动态开节点线段树)
题意 题目链接 Sol 树链剖分板子 + 动态开节点线段树板子 #include<bits/stdc++.h> #define Pair pair<int, int> #def ...
- [SDOI2014]旅行
洛谷 P3313 [SDOI2014]旅行 https://www.luogu.org/problem/show?pid=3313 题目描述 S国有N个城市,编号从1到N.城市间用N-1条双向道路连接 ...
- BZOJ 3531: [Sdoi2014]旅行 [树链剖分]
3531: [Sdoi2014]旅行 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1685 Solved: 751[Submit][Status] ...
- 【BZOJ3531】[Sdoi2014]旅行 树链剖分+动态开点线段树
[BZOJ3531][Sdoi2014]旅行 Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天 ...
随机推荐
- 获取验证码随机字符串@return string $captcha,随机验证码文字
<?php//验证码工具类class Captcha{//属性private $width;private $height;private $fontsize;private $pixes;pr ...
- date 命令之日期和秒数转换
时间转为秒数 date -d "2012-11-12 13:00:00" +"%s" 描述转为日期 date -d@1352692800 +"%Y-% ...
- 它是对 ACME(automated certificate management environment) 协议的实现,只要实现了 ACME 协议的客户端都可以跟它交互。
它是对 ACME(automated certificate management environment) 协议的实现,只要实现了 ACME 协议的客户端都可以跟它交互. https://mp.we ...
- sql 对某列取值进行if判断
select if(area_id =350000, 1, 2) as area_id from my_table 取地区编号为350000的设置成 1, 其他的设置成2
- CF1044B Intersecting Subtrees 构造+树论
正解:构造 解题报告: 传送门 又是一道交互题!爱了爱了! 这题真的,极妙!非常神仙!就非常非常思维题! 直接说解法了吼 说起来实在是简单鸭 就是先问一个对方的联通块中的一个点在我这儿的编号,记为x ...
- 查看win信任的证书办法机构(CA机构的公钥)
cmd mmc
- query:callback
function getName(callback) { setTimeout(function() { callback('Aaron') }, 1000) } //等待callback回调 get ...
- iOS中Date和NString的相互转换
必须知道的内容 G: 公元时代,例如AD公元 yy: 年的后2位 yyyy: 完整年 MM: 月,显示为1-12 MMM: 月,显示为英文月份简写,如 Jan ...
- (转)Elasticsearch 的坑爹事——记录一次mapping field修改过程
Elasticsearch 的坑爹事 本文记录一次Elasticsearch mapping field修改过程 团队使用Elasticsearch做日志的分类检索分析服务,使用了类似如下的_mapp ...
- PAT 1049 Counting Ones[dp][难]
1049 Counting Ones (30)(30 分) The task is simple: given any positive integer N, you are supposed to ...