luoguP2590 [ZJOI2008]树的统计 [树链剖分] [TLE的LCT]
题目描述
一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。
我们将以下面的形式来要求你对这棵树完成一些操作:
I. CHANGE u t : 把结点u的权值改为t
II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值
III. QSUM u v: 询问从点u到点v的路径上的节点的权值和
注意:从点u到点v的路径上的节点包括u和v本身
输入输出格式
输入格式:
输入文件的第一行为一个整数n,表示节点的个数。
接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。
接下来一行n个整数,第i个整数wi表示节点i的权值。
接下来1行,为一个整数q,表示操作的总数。
接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。
输出格式:
对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。
输入输出样例
4
1 2
2 3
4 1
4 2 1 3
12
QMAX 3 4
QMAX 3 3
QMAX 3 2
QMAX 2 3
QSUM 3 4
QSUM 2 1
CHANGE 1 5
QMAX 3 4
CHANGE 3 6
QMAX 3 4
QMAX 2 4
QSUM 3 4
4
1
2
2
10
6
5
6
5
16
说明
对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。
这题本身应该是一题树链剖分果题。。QAQ
//不用lazy-tag真是爽!
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
#define inf 0x3f3f3f3f
#define ls x<<1
#define rs x<<1|1 int read(){
char ch;
int re=;
bool flag=;
while((ch=getchar())!='-'&&(ch<''||ch>''));
ch=='-'?flag=:re=ch-'';
while((ch=getchar())>=''&&ch<='') re=re*+ch-'';
return flag?-re:re;
} struct Edge{
int to,nxt;
Edge(int to=,int nxt=):
to(to),nxt(nxt){}
}; struct Segment{
int l,r,su,mx;
Segment(){
mx=-inf;
}
}; const int maxn=; int n,m,cnt=,dc=;
int head[maxn],val[maxn];
int top[maxn],dep[maxn],fa[maxn],id[maxn],son[maxn],sz[maxn];
Edge G[maxn<<];
Segment T[maxn<<]; inline void a_ed(int from,int to){
G[++cnt]=Edge(to,head[from]),head[from]=cnt;
G[++cnt]=Edge(from,head[to]),head[to]=cnt;
} inline void push_up(int x){
T[x].mx=max(T[ls].mx,T[rs].mx);
T[x].su=T[ls].su+T[rs].su;
} void build(int x,int l,int r){
T[x].l=l,T[x].r=r;
if(l==r){
T[x].su=T[x].mx=val[l];
return;
}
int mid=l+r>>;
build(ls,l,mid); build(rs,mid+,r);
push_up(x);
} void update(int x,int M,int c){
if(T[x].l==T[x].r){
T[x].su=T[x].mx=c;
return;
}
int mid=T[x].l+T[x].r>>;
if(M<=mid) update(ls,M,c);
else update(rs,M,c);
push_up(x);
} int query(int x,int L,int R,bool kind){
if(L<=T[x].l&&T[x].r<=R)
if(kind) return T[x].su;
else return T[x].mx;
int mid=T[x].l+T[x].r>>;
if(R<=mid) return query(ls,L,R,kind);
else if(L>mid) return query(rs,L,R,kind);
else{
if(kind) return query(ls,L,mid,kind)+query(rs,mid+,R,kind);
else return max(query(ls,L,mid,kind),query(rs,mid+,R,kind));
}
} void dfs1(int no,int p){
fa[no]=p;
sz[no]=;
dep[no]=dep[p]+;
for(int e=head[no];e;e=G[e].nxt){
int nt=G[e].to;
if(nt!=p){
dfs1(nt,no);
sz[no]+=sz[nt];
if(!son[no]||sz[nt]>sz[son[no]])
son[no]=nt;
}
}
} void dfs2(int no,int p){
if(!son[no]) return;
top[son[no]]=top[no];
id[son[no]]=++dc;
dfs2(son[no],no);
for(int e=head[no];e;e=G[e].nxt){
int nt=G[e].to;
if(nt!=p&&nt!=son[no]){
top[nt]=nt;
id[nt]=++dc;
dfs2(nt,no);
}
}
} int calc(int x,int y,bool kind){
int sum=,f1=top[x],f2=top[y];
if(!kind) sum=-inf;
while(f1!=f2){
if(dep[f1]<dep[f2]){ swap(f1,f2),swap(x,y); }
if(kind)
sum+=query(,id[f1],id[x],kind);
else
sum=max(sum,query(,id[f1],id[x],kind));
x=fa[f1];
f1=top[x];
}
if(dep[x]>dep[y]) swap(x,y);
if(kind) sum+=query(,id[x],id[y],kind);
else sum=max(sum,query(,id[x],id[y],kind));
return sum;
} int main(){
// freopen("temp.in","r",stdin);
n=read();
for(int i=,from,to;i<n;i++){
from=read(); to=read();
a_ed(from,to);
}
dfs1(,);
top[]=;
id[]=;
dfs2(,);
for(int i=;i<=n;i++) val[id[i]]=read();
build(,,n);
m=read();
char opt[];
int x,y;
while(m--){
scanf("%s",opt);
x=read(),y=read();
switch(opt[]){
case 'H':{
update(,id[x],y);
break;
}
case 'M':{
printf("%d\n",calc(x,y,));
break;
}
default:{
printf("%d\n",calc(x,y,));
break;
}
}
}
return ;
}
刚学了LCT的我。。想用LCT过了这一题。。
可是。。T了。。QAQ
顺便终于明白、、把一堆变量包进一个结构体里还不用指针构成的splay还不如拆成一个个数组。。
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
#define rint register int
#define inf 0x3f3f3f3f int read(){
char ch;
int re=;
bool flag=;
while((ch=getchar())!='-'&&(ch<''||ch>''));
ch=='-'?flag=:re=ch-'';
while((ch=getchar())>=''&&ch<='') re=re*+ch-'';
return flag?-re:re;
} struct Edge{
int to,nxt;
Edge(int to=,int nxt=):
to(to),nxt(nxt){}
}; const int maxn=; int n,m,cnt=,top;
//struct 变 数组
int ch[maxn][],su[maxn],mx[maxn],fa[maxn],rev[maxn];
int head[maxn],val[maxn],stk[maxn];
Edge G[maxn<<]; inline void a_ed(int from,int to){
G[++cnt]=Edge(to,head[from]);
head[from]=cnt;
G[++cnt]=Edge(from,head[to]);
head[to]=cnt;
} inline void push_up(int x){
mx[x]=max(mx[ch[x][]],max(mx[ch[x][]],val[x]));
su[x]=su[ch[x][]]+su[ch[x][]]+val[x];
} inline void push_down(int x){
if(rev[x]){
rev[ch[x][]]^=,rev[ch[x][]]^=;
swap(ch[x][],ch[x][]);
rev[x]=;
}
} inline bool isroot(int x){
return ch[fa[x]][]!=x&&ch[fa[x]][]!=x;
} void rot(int x){
int y=fa[x],z=fa[y],l,r;
fa[x]=z;
if(!isroot(y)) ch[z][ch[z][]==y]=x;
if(ch[y][]==x) l=;
else l=;
r=l^;
fa[ch[x][r]]=y;
ch[y][l]=ch[x][r];
fa[y]=x;
ch[x][r]=y;
push_up(y),push_up(x);
} void splay(int x){
top=; stk[top]=x;
for(rint i=x;!isroot(i);i=fa[i]) stk[++top]=fa[i];
for(rint i=top;i;i--) push_down(stk[i]);
while(!isroot(x)){
int y=fa[x],z=fa[y];
if(!isroot(y)){
if((ch[y][]==x)^(ch[z][]==y)) rot(x);
else rot(y);
}
rot(x);
}
} void acc(int x){
int t=;
while(x){
splay(x);
ch[x][]=t;
push_up(x);
t=x; x=fa[x];
}
} void make_root(int x){ acc(x),splay(x),rev[x]^=; } void split(int x,int y){ make_root(x),acc(y),splay(y); } void dfs(int no,int fat){
fa[no]=fat;
for(rint e=head[no];e;e=G[e].nxt)
if(G[e].to!=fat)
dfs(G[e].to,no);
} int main(){
// freopen("temp.in","r",stdin);
n=read();
for(rint i=,from,to;i<n;i++){
from=read(),to=read();
a_ed(from,to);
}
memset(mx,-inf,(n+)<<);
for(rint i=;i<=n;i++){
val[i]=read();
su[i]=mx[i]=val[i];
}
dfs(,);
char opt[]; int x,y;
m=read();
while(m--){
scanf("%s",opt);
x=read(),y=read();
switch(opt[]){
case 'H':{
acc(x);
splay(x);
val[x]=y;
push_up(x);
break;
}
case 'M':{
split(x,y);
printf("%d\n",mx[y]);
break;
}
default:{
split(x,y);
printf("%d\n",su[y]);
break;
}
}
}
return ;
}
luoguP2590 [ZJOI2008]树的统计 [树链剖分] [TLE的LCT]的更多相关文章
- BZOJ 1036: [ZJOI2008]树的统计Count-树链剖分(点权)(单点更新、路径节点最值、路径求和)模板,超级认真写了注释啊啊啊
1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 23015 Solved: 9336[Submit ...
- 树的统计Count---树链剖分
NEFU专项训练十和十一——树链剖分 Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t ...
- luoguP2590 [ZJOI2008]树的统计(树链剖分)
luogu P2590 [ZJOI2008]树的统计 题目 #include<iostream> #include<cstdlib> #include<cstdio> ...
- BZOJ1036[ZJOI2008]树的统计——树链剖分+线段树
题目描述 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v ...
- [ZJOI2008]树的统计——树链剖分
本题是一个树链剖分裸题,由于比较菜,老是RE,后来发现是因为使用了全局变量. /************************************************************ ...
- [luogu P2590 ZJOI2008] 树的统计 (树链剖分)
题目描述 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w. 我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u ...
- 洛谷P2590 [ZJOI2008] 树的统计 [树链剖分]
题目传送门 树的统计 题目描述 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w. 我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t ...
- BZOJ 1036 树的统计-树链剖分
[ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 12904 Solved: 5191[Submit][Status ...
- BZOJ-1036 树的统计Count 链剖线段树(模板)=(树链剖分+线段树)
潇爷昨天刚刚讲完...感觉得还可以...对着模板打了个模板...还是不喜欢用指针.... 1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Lim ...
随机推荐
- Python中的try-finally
>>> try: ... raise KeyboardInterrupt ... finally: ... print('Goodbye, world!') ... Goodbye, ...
- Concurrent - 并发框架
原创转载请注明出处:https://www.cnblogs.com/agilestyle/p/11426833.html SynchronizedMap和ConcurrentHashMap有什么区别? ...
- iOS项目开发中的知识点与问题收集整理②
1.点击UIButton 无法产生触摸事件 如果在UIImageView中添加了一个按钮,你会发现在默认情况下这个按钮是无法被点击的,需要设置UIImageView的userInteractio ...
- 【leetcode】997. Find the Town Judge
题目如下: In a town, there are N people labelled from 1 to N. There is a rumor that one of these people ...
- shell倒计时下班时间
#!/bin/sh offWorkTime="19:00:00" offWorkHour=${offWorkTime::} offWorkMinute=${offWorkTime: ...
- css float 浮动
CSS Float(浮动) 什么是 CSS Float(浮动)?大理石平台价格 CSS 的 Float(浮动),会使元素向左或向右移动,其周围的元素也会重新排列. Float(浮动),往往是用于图像, ...
- 2019牛客多校第五场H - subsequence 2 拓扑
H - subsequence 2 题意 要你使用前\(m\)个小写字母构造一个长度为\(n\)的字符串 有\(m*(m-1)/2\)个限制条件: \(c_{1} .c_{2}. len\):表示除去 ...
- Python基础(三):简化除法判断、分析apache访问日志、扫描存活主机、利用多线程实现ssh并发访问
一.简化除法判断 目标: 编写mydiv.py脚本,主要要求如下: 提示用户输入一个数字作为除数 如果用户按下Ctrl+C或Ctrl+D则退出程序 如果用户输入非数字字符,提示用户应该输入数字 如果用 ...
- rsync和rsync后台模式
注意(有软连接的rsync同步,-L可以把软链接里的当普通文件同步.-l 只同步软链接不同步软链接指向的目录或文件) rsync命令详解 rsync -a 归档模式 ,表示以递归方式传输文件,并保持所 ...
- 前端每日实战:73# 视频演示如何用纯 CSS 创作一只卡通狐狸
效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/OEKZed 可交互视频 此视频是可 ...