您的位置:首页 > 其它

【BZOJ 1036】[ZJOI2008]树的统计Count 【树链剖分+线段树】

2016-10-27 12:16 531 查看
裸题..

开始的代码有个bug,开始的
build()
函数是这样写的:

void build(int u,int l,int r){
tr[u].l=l,tr[u].r=r;
if(l==r){
tr[u].mx=tr[u].sum=val[l];
return;
};
int mid=(l+r)>>1;
build(ls,l,mid);
build(rs,mid+1,r);
pushup(u);
}


这样写为什么会挂啊??

修改方式:

if(l==r)return;


然后build好后在外面单点修改

fs(i,1,n)update(1,pos[i],val[i]);


这里不是很懂啊,我觉得我开始的写法也没错啊qwq

可是不知道为什么过不了。。

宝宝心好痛。

Update:中午回去突然发现..自己又智障了..因为改的val[i]在线段树里的编号不是i..然而因为过了样例所以我居然没有发现这点..zz..真是智障了..

样例这种东西,哪怕算法写错了都能随便过..真是醉了..

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<cctype>
using namespace std;
#define g() getchar()
#define d(x) isdigit(x)
#define fs(i,s,t) for(int i=(s);i<=(t);i++)
char ch;bool sg;
template<class T>
inline void F(T& x){
for(sg=false,ch=g();!d(ch);ch=='-'?sg=true:1,ch=g());
for(x=0;d(ch);x=x*10+ch-'0',ch=g());sg?x=-x:1;
}
#define N 30010
int n,Q,head
,eid=0,val
;struct Edge{int to,next;}e[N<<1];
inline void adde(int u,int v){e[++eid].to=v;e[eid].next=head[u];head[u]=eid;}
int size
,dep
,fa
;
void dfs1(int x){//找重边
size[x]=1;
for(int i=head[x];~i;i=e[i].next){
if(e[i].to==fa[x])continue;
int v = e[i].to;
dep[v] = dep[x]+1;fa[v]=x;
dfs1(v);
size[x]+=size[v];
}
}
int tid,pos
,top
;
void dfs2(int x,int topx){//连重边成重链
++tid;pos[x]=tid;top[x]=topx;int k=0;//找重儿子
for(int i=head[x];~i;i=e[i].next)
if(dep[e[i].to]>dep[x]&&size[e[i].to]>size[k])
k = e[i].to;
if(k==0)return;
dfs2(k,topx);
for(int i=head[x];~i;i=e[i].next)
if(dep[e[i].to]>dep[x]&&e[i].to!=k)
dfs2(e[i].to,e[i].to);
}
struct SegTree{int l,r,mx,sum;}tr[N<<2];
#define ls (u<<1)
#define rs (u<<1|1)
inline void pushup(int u)
{
tr[u].mx=max(tr[ls].mx,tr[rs].mx);
tr[u].sum=tr[ls].sum+tr[rs].sum;
}
void build(int u,int l,int r){
tr[u].l=l,tr[u].r=r;
if(l==r)return;
int mid=(l+r)>>1;
build(ls,l,mid);
build(rs,mid+1,r);
pushup(u);
}
void update(int u,int x,int k){
if(tr[u].l==tr[u].r){tr[u].mx=tr[u].sum=k;return;}
int mid=(tr[u].l+tr[u].r)>>1;
if(x<=mid)update(ls,x,k);
else update(rs,x,k);
pushup(u);
}
int querymax(int u,int x,int y){
if(x<=tr[u].l&&tr[u].r<=y)return tr[u].mx;
int mid=(tr[u].l+tr[u].r)>>1;
if(y<=mid)return querymax(ls,x,y);
else if(x>mid)return querymax(rs,x,y);
else return max(querymax(ls,x,y),querymax(rs,x,y));
}
int querysum(int u,int x,int y){
if(x<=tr[u].l&&tr[u].r<=y)return tr[u].sum;
int mid=(tr[u].l+tr[u].r)>>1;
if(y<=mid)return querysum(ls,x,y);
else if(x>mid)return querysum(rs,x,y);
else return querysum(ls,x,y)+querysum(rs,x,y);
}
int askmax(int x,int y){
int ret = -0x7fffffff;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
ret = max(ret,querymax(1,pos[top[x]],pos[x]));
x = fa[top[x]];
}
if(pos[x]>pos[y])swap(x,y);
ret=max(ret,querymax(1,pos[x],pos[y]));
return ret;
}
int asksum(int x,int y){
int ret = 0;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
ret += querysum(1,pos[top[x]],pos[x]);
x = fa[top[x]];
}
if(pos[x]>pos[y])swap(x,y);
ret+=querysum(1,pos[x],pos[y]);
return ret;
}
int main(){
F(n);int a,b;char op[10];
memset(head,-1,sizeof(head));
fs(i,1,n-1){F(a),F(b);adde(a,b);adde(b,a);}
fs(i,1,n)F(val[i]);
dfs1(1);
dfs2(1,1);
build(1,1,n);
fs(i,1,n)update(1,pos[i],val[i]);
F(Q);
while(Q--){
scanf("%s%d%d",op,&a,&b);
if(*op=='C')val[a]=b,update(1,pos[a],b);
else if(*(op+1)=='M')printf("%d\n",askmax(a,b));
else printf("%d\n",asksum(a,b));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  树链剖分