bzoj 1036 //1036: [ZJOI2008]树的统计Count 树链剖分
bzoj 1036 //1036: [ZJOI2008]树的统计Count //在线测评地址https://www.lydsy.com/JudgeOnline/problem.php?id=1036
更多题解,详见https://blog.csdn.net/mrcrack/article/details/90228694BZOJ刷题记录
1036 | Accepted | 5560 kb | 3208 ms | C++/Edit | 3362 B |
//1036: [ZJOI2008]树的统计Count
//在线测评地址https://www.lydsy.com/JudgeOnline/problem.php?id=1036
//n=30000,w=30000,n*w=9*10^8 int不会溢出。
//采用树链剖分算法,若不清楚,详见https://blog.csdn.net/mrcrack/article/details/102884839
//树链剖分算法,遇到段错误,算是常事了。
//反复排查,linux在main函数内不好排查段错误,必须深入到具体函数内部去,增加了不少工作量。
/*
a[k].l=a[k].r=l,a[k].mx=a[k].sum=v[rk[l]];//此处错写成a[k].l=a[k].r,a[k].mx=a[k].sum=v[rk[l]];查了2个小时.2019-11-3 20:39
一处不起眼的错误啊。
*/
//样例通过,提交AC.2019-11-3 20:43 收获,对线段树节点的改、查,理解更深刻了。
#include
#include
#define lson k<<1
#define rson k<<1|1
#define maxn 30100
struct node1{
int to,next;
}e[maxn<<1];
struct node2{
int l,r,sum,mx;
}a[maxn<<2];
int v[maxn],n,head[maxn],R=1,d[maxn],fa[maxn],size[maxn],son[maxn],id[maxn],rk[maxn],cnt,top[maxn];
int max(int a,int b){
return a>b?a:b;
}
void add_edge(int u,int v){
cnt++,e[cnt].to=v,e[cnt].next=head[u],head[u]=cnt;
}
void dfs1(int x){
int v,b;
d[x]=d[fa[x]]+1,size[x]=1;
for(b=head[x];b;b=e[b].next){
v=e[b].to;
if(v!=fa[x]){
fa[v]=x,dfs1(v),size[x]+=size[v];
if(size[son[x]]
}
}
void dfs2(int x,int tp){
int v,b;
top[x]=tp,cnt++,rk[cnt]=x,id[x]=cnt;
if(son[x])dfs2(son[x],tp);
for(b=head[x];b;b=e[b].next){
v=e[b].to;
if(v!=fa[x]&&v!=son[x])dfs2(v,v);
}
}
void pushup(int k){
a[k].sum=a[lson].sum+a[rson].sum;
a[k].mx=max(a[lson].mx,a[rson].mx);
}
void update(int l,int r,int c,int k){
int mid=(a[k].l+a[k].r)/2;
if(l<=a[k].l&&a[k].r<=r){
a[k].sum=a[k].mx=c;
return;
}
if(l<=mid)update(l,r,c,lson);
if(mid+1<=r)update(l,r,c,rson);
pushup(k);
}
int qmax(int l,int r,int k){
int mid=(a[k].l+a[k].r)/2,ret=-30100;//此处错写成int mid=(a[k].l+a[k].r)/2,ret=-1;
if(l<=a[k].l&&a[k].r<=r){
return a[k].mx;
}
if(l<=mid)ret=max(ret,qmax(l,r,lson));
if(mid+1<=r)ret=max(ret,qmax(l,r,rson));
return ret;
}
void swap(int *a,int *b){
int t;
t=*a,*a=*b,*b=t;
}
int qmaxs(int x,int y,int k){
int ret=-30100;//此处错写成int ret=-1;
while(top[x]!=top[y]){
if(d[top[x]]
}
if(id[x]>id[y])swap(&x,&y);
ret=max(ret,qmax(id[x],id[y],1));//此处错写成ret=(ret,qmax(id[x],id[y],1));
return ret;
}
int qsum(int l,int r,int k){
int mid=(a[k].l+a[k].r)/2,ret=0;
if(l<=a[k].l&&a[k].r<=r){
return a[k].sum;
}
if(l<=mid)ret+=qsum(l,r,lson);
if(mid+1<=r)ret+=qsum(l,r,rson);
return ret;
}
int qsums(int x,int y,int k){
int ret=0;
while(top[x]!=top[y]){
if(d[top[x]]
}
if(id[x]>id[y])swap(&x,&y);
ret+=qsum(id[x],id[y],1);
return ret;
}
void build(int l,int r,int k){
int mid=(l+r)/2;
if(l==r){
a[k].l=a[k].r=l,a[k].mx=a[k].sum=v[rk[l]];//此处错写成a[k].l=a[k].r,a[k].mx=a[k].sum=v[rk[l]];查了2个小时.2019-11-3 20:39
return;
}
build(l,mid,lson);
build(mid+1,r,rson);
a[k].l=l,a[k].r=r,pushup(k);
}
int main(){
int i,a,b,q;
char cmd[10];
scanf("%d",&n),memset(head,0,sizeof(head)),cnt=0;
for(i=1;i
memset(son,0,sizeof(son)),fa[R]=0,d[0]=0,dfs1(R);
cnt=0,dfs2(R,R);
build(1,n,1);
scanf("%d",&q);
while(q--){
scanf("%s",cmd);
if(cmd[1]=='M')scanf("%d%d",&a,&b),printf("%d\n",qmaxs(a,b,1));
else if(cmd[1]=='S')scanf("%d%d",&a,&b),printf("%d\n",qsums(a,b,1));
else if(cmd[1]=='H')scanf("%d%d",&a,&b),update(id[a],id[a],b,1);
}
return 0;
}