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 ...
随机推荐
- Delphi 访问https /SSL、OpenSSL
访问 Web 网站,最简单用法直接使用 TIdHTTP 控件: 例如:AA := IdHTTP1.Get('www.baidu.com.'); 访问 https 的网站,需要 SSL 库. 在 Win ...
- c++11 继承构造函数
若基类拥有数量众多的不同版本的构造函数,而派生类中只有一些成员函数,则对于派生类而言,其构造函数就等同于构造基类. struct A { A(int i) {} A(double d, int i) ...
- 每天一个Linux命令:rm(5)
rm rm命令可以删除一个目录中的一个或多个文件或目录,也可以将某个目录及其下属的所有文件及其子目录均删除掉.对于链接文件,只是删除整个链接文件,而原有文件保持不变 注意:使用rm命令要格外小心.因为 ...
- 阿里云 Centos 7 PHP7环境配置 LNMP
首先更新系统软件 $ yum update 安装nginx 1.安装nginx源 $ yum localinstall http://nginx.org/packages/centos/7/noarc ...
- android.os.NetworkOnMainThreadException异常 (转)
转:http://blog.csdn.net/wotoumingzxy/article/details/7797295 这个异常大概意思是在主线程访问网络时出的异常. Android在4.0之前的版本 ...
- memset函数及原补反码关系
memset函数及原补反码关系 计算机存储的是补码 几组常用的memset函数初始化值 10000000 128 10000000 10000000 10000000 10000000 -213906 ...
- dubbo系列学习好文章
1. dubbo入门学习(一)-----分布式基础理论.架构发展以及rpc.dubbo核心概念 https://www.cnblogs.com/alimayun/p/10982650.html 2. ...
- CentOS7.5 yum 安装与配置MySQL5.7.24
安装环境:CentOS7 64位 MINI版,安装MySQL5.7 1.配置YUM源 在MySQL官网中下载YUM源rpm安装包:https://dev.mysql.com/downloads/rep ...
- js少写if语句
1.if else if (bool) { a =1; } else { a = 2 } // 简写 a = bool ? 1 : 2: 2.if if (bool) { a = fn() } //简 ...
- Haproxy+ssl+nvm+forever
1 nvm介绍 NVM(Node version manager)顾名思义,就是Node.js的版本管理软件,可以轻松的在Node.js各个版本间切换,项目源码在GitHub: #安装git客户端 [ ...