题目描述

一棵树上有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”的操作,每行输出一个整数表示要求输出的结果。

输入输出样例

输入样例#1:

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
输出样例#1:

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]的更多相关文章

  1. BZOJ 1036: [ZJOI2008]树的统计Count-树链剖分(点权)(单点更新、路径节点最值、路径求和)模板,超级认真写了注释啊啊啊

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 23015  Solved: 9336[Submit ...

  2. 树的统计Count---树链剖分

    NEFU专项训练十和十一——树链剖分 Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t ...

  3. luoguP2590 [ZJOI2008]树的统计(树链剖分)

    luogu P2590 [ZJOI2008]树的统计 题目 #include<iostream> #include<cstdlib> #include<cstdio> ...

  4. BZOJ1036[ZJOI2008]树的统计——树链剖分+线段树

    题目描述 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v ...

  5. [ZJOI2008]树的统计——树链剖分

    本题是一个树链剖分裸题,由于比较菜,老是RE,后来发现是因为使用了全局变量. /************************************************************ ...

  6. [luogu P2590 ZJOI2008] 树的统计 (树链剖分)

    题目描述 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w. 我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u ...

  7. 洛谷P2590 [ZJOI2008] 树的统计 [树链剖分]

    题目传送门 树的统计 题目描述 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w. 我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t ...

  8. BZOJ 1036 树的统计-树链剖分

    [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 12904 Solved: 5191[Submit][Status ...

  9. BZOJ-1036 树的统计Count 链剖线段树(模板)=(树链剖分+线段树)

    潇爷昨天刚刚讲完...感觉得还可以...对着模板打了个模板...还是不喜欢用指针.... 1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Lim ...

随机推荐

  1. 【leetcode】1002. Find Common Characters

    题目如下: Given an array A of strings made only from lowercase letters, return a list of all characters ...

  2. delphi中SendMessage使用说明

    SendMessage基础知识 函数功能:该函数将指定的消息发送到一个或多个窗口.此函数为指定的窗口调用窗口程序,直到窗口程序处理完消息再返回.而函数PostMessage不同,将一个消息寄送到一个线 ...

  3. 20175223 《Java程序设计》第十一周学习总结

    目录 教材学习内容总结 代码调试中的问题和解决过程 1. Linux中编程实现计算器方法乘法报错,但 IDEA 中可以. [代码托管] 学习进度条 参考资料 目录 教材学习内容总结 因未熟练掌握第十章 ...

  4. QTP学习笔记---datatable应用

    DataTable应用1.定位数据行 DataTable.GetSheet() 2.获取当前行 GetCurrentRow3.获取指定行的值 getValueByRow = DataTable.Get ...

  5. php把网络图片转Base64编码。(php将图片链接直接转化为base64编码)

    /** 把网络图片图片转成base64 * @param string $img 图片地址 * @return string */ /*网络图片转为base64编码*/ public function ...

  6. 96、搬家到csdn

    大家好: 今天开始会将所有的博客搬家到CSDN,以后请参考CSDN上的博客:http://blog.csdn.net/u012416045 谢谢 维真

  7. EOJ 1058. 挤模具 (多边形面积)

    题目链接:1058. 挤模具 题意 给出模具的底和体积,求模具的高. 思路 模具的底为多边形,因此求出多边形面积,用体积除以底的面积就是答案. 多边形的面积求解见 EOJ 1127. 多边形面积(计算 ...

  8. upc组队赛3 Iranian ChamPions Cup

    Iranian ChamPions Cup 题目描述 The Iranian ChamPions Cup (ICPC), the most prestigious football league in ...

  9. GNU Linux 64汇编学习

    函数调用传参: 第一个参数:rdi, 第二个参数:rsi 函数调用栈结构: 返回值 第一个参数 第二个参数 +----------+ rsp-24 | a | +----------+ rsp-16 ...

  10. Spring Boot实现通用的接口参数校验

    Spring Boot实现通用的接口参数校验 Harries Blog™ 2018-05-10 2418 阅读 http ACE Spring App API https AOP apache IDE ...