您的位置:首页 > 其它

[bzoj1036]:[ZJOI2008]树的统计Count(树链剖分)

2017-09-30 12:23 441 查看
传送门

十分裸的一个树链剖分,这也是我第一次过树剖题,好激动!

关于这个算法我不多说,自己百度。

代码:

/**************************************************************
Problem: 1036
User: stone41123
Language: C++
Result: Accepted
Time:2484 ms
Memory:5676 kb
****************************************************************/

#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline int read(){
int x=0;char ch=' ';int f=1;
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')f=-1,ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*f;
}
struct edge{
int to,next;
}e[60001];
int n,tot,q;
int v[30001];
int head[30001];
inline void addedge(int x,int y){
e[++tot].to=y;e[tot].next=head[x];head[x]=tot;
}
int father[30001];
int size[30001];
int top[30001];
int heavy[30001];
int dep[30001];
void dfs1(int x,int fa){
father[x]=fa;
size[x]=1;
dep[x]=dep[fa]+1;
for(int i=head[x];i;i=e[i].next){
int u=e[i].to;
if(u==fa)continue;
dfs1(u,x);
size[x]+=size[u];
if(size[u]>size[heavy[x]]){
heavy[x]=u;
}
}
}
int a[30001];
int mp[30001];
int cnt;
int id[30001];
void dfs2(int x,int first){
top[x]=first;
id[++cnt]=x;
mp[x]=cnt;
a[cnt]=v[x];
if(size[x]==1){
return;
}
dfs2(heavy[x],first);
for(int i=head[x];i;i=e[i].next){
int u=e[i].to;
if(u==heavy[x]||u==father[x]){
continue;
}
dfs2(u,u);
}
}
int sum[30001*4];
int mx[30001*4];
inline void pushup(int rt){
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
mx[rt]=max(mx[rt<<1],mx[rt<<1|1]);
}
void build(int rt,int l,int r){
if(l==r){
sum[rt]=mx[rt]=a[l];
return;
}
int mid=(l+r)>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
pushup(rt);
}
void update(int rt,int l,int r,int pos,int x){
if(l==r){
sum[rt]=mx[rt]=x;
return;
}
int mid=(l+r)>>1;
if(pos<=mid)update(rt<<1,l,mid,pos,x);
else update(rt<<1|1,mid+1,r,pos,x);
pushup(rt);
}
int qmax(int rt,int l,int r,int L,int R){
if(L<=l&&r<=R){
return mx[rt];
}
int mid=(l+r)>>1;
int ans=-0x7fffffff;
if(L<=mid)ans=max(ans,qmax(rt<<1,l,mid,L,R));
if(mid+1<=R)ans=max(ans,qmax(rt<<1|1,mid+1,r,L,R));
return ans;
}
int qsum(int rt,int l,int r,int L,int R){
if(L<=l&&r<=R){
return sum[rt];
}
int mid=(l+r)>>1;
int ans=0;
if(L<=mid)ans+=qsum(rt<<1,l,mid,L,R);
if(mid+1<=R)ans+=qsum(rt<<1|1,mid+1,r,L,R);
return ans;
}
int query_max(int x,int y){
int ans=-0x7fffffff;
int tx=top[x];
int ty=top[y];
while(tx!=ty){
if(dep[tx]<dep[ty]){
swap(x,y);swap(tx,ty);
}
ans=max(ans,qmax(1,1,n,mp[tx],mp[x]));
x=father[tx];
tx=top[x];
}
if(dep[x]<dep[y]){
swap(x,y);swap(tx,ty);
}
return max(ans,qmax(1,1,n,mp[y],mp[x]));
}
int query_sum(int x,int y){
int ans=0;
int tx=top[x];
int ty=top[y];
while(tx!=ty){
if(dep[tx]<dep[ty]){
swap(x,y);swap(tx,ty);
}
ans+=qsum(1,1,n,mp[tx],mp[x]);
x=father[tx];
tx=top[x];
}
if(dep[x]<dep[y]){
swap(x,y);swap(tx,ty);
}
return ans+qsum(1,1,n,mp[y],mp[x]);
}
int main(){
n=read();
for(int i=1;i<n;i++){
int x=read(),y=read();
addedge(x,y);addedge(y,x);
}
for(int i=1;i<=n;i++)v[i]=read();
q=read();
dfs1(1,0);
dfs2(1,1);
build(1,1,n);
char cmp0[20]="CHANGE";
char cmp1[20]="QMAX";
char cmp2[20]="QSUM";
for(int i=1;i<=q;i++){
char s[20];
scanf("%s",s);
if(strcmp(cmp0,s)==0){
int pos=read(),x=read();
update(1,1,n,mp[pos],x);
}
else if(strcmp(cmp1,s)==0){
int x=read(),y=read();
printf("%d\n",query_max(x,y));
}
else{
int x=read(),y=read();
printf("%d\n",query_sum(x,y));
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: