您的位置:首页 > 其它

BZOJ1036:[ZJOI2008]树的统计Count 树链剖分 / LCT

2014-04-09 20:06 337 查看
树链剖分网上的资料比较详细了。

其实我一直很怕dfs爆栈啊。。

上代码:

#include <cstdio>
#include <algorithm>
#define rep(i,l,r) for (int i=l;i<=r;++i)
#define per(i,r,l) for (int i=r;i>=l;--i)
#define feh(k,v) for (int k=first[v];k;k=next[k])
#define gt getchar()
int getx(){
char c;int x;bool pd=false;
for (c=gt;c!='-'&&(c<'0'||c>'9');c=gt);
if (c=='-') c=getchar(),pd=true;
for (x=0;c>='0'&&c<='9';c=gt)
x=(x<<3)+(x<<1)+c-'0';
return pd?-x:x;
}
int Max(const int &a,const int &b){return a<b?b:a;}
int upmax(int &a,const int &b){return a<b?a=b,1:0;}
const int MAX_N=30050,INF=~0U>>2;
int first[MAX_N],next[MAX_N*2],to[MAX_N*2],tal=0;
void tjb(int x,int y){
next[++tal]=first[x];
first[x]=tal,to[tal]=y;
next[++tal]=first[y];
first[y]=tal,to[tal]=x;
}
struct SegmentTree{
int max[MAX_N<<2],sum[MAX_N<<2];
#define lcv v<<1
#define rcv v<<1|1
#define lc v<<1,l,mid
#define rc v<<1|1,mid+1,r
inline void up(int v){
max[v]=Max(max[lcv],max[rcv]);
sum[v]=sum[lcv]+sum[rcv];
}
void modify(int v,int l,int r,int p,int x){
if (l==r){max[v]=sum[v]=x;return;}
int mid=l+r>>1;
if (p<=mid) modify(lc,p,x);
else modify(rc,p,x);
up(v);
}
int qmax(int v,int l,int r,int s,int t){
if (s<=l&&r<=t) return max[v];
int mid=l+r>>1,res=-INF;
if (s<=mid) res=qmax(lc,s,t);
if (t> mid) upmax(res,qmax(rc,s,t));
return res;
}
int qsum(int v,int l,int r,int s,int t){
if (s<=l&&r<=t) return sum[v];
int mid=l+r>>1,res=0;
if (s<=mid) res+=qsum(lc,s,t);
if (t> mid) res+=qsum(rc,s,t);
return res;
}
}T;
int n,q;
int w[MAX_N];
int fa[MAX_N],deep[MAX_N],size[MAX_N];
int hson[MAX_N];
int dfs1(int v,int faa,int dep){
deep[v]=dep,fa[v]=faa,size[v]=1;
int &son=hson[v]=0;
feh(k,v) if (to[k]!=faa){
int tp=dfs1(to[k],v,dep+1);
if (tp>size[son]) son=to[k];
size[v]+=tp;
}
return size[v];
}
int pos[MAX_N],top[MAX_N];
int Time=0;
void dfs2(int v,bool heavy){
pos[v]=++Time;
T.modify(1,1,n,pos[v],w[v]);
top[v]=heavy?top[fa[v]]:v;
if (hson[v]) dfs2(hson[v],true);
feh(k,v) if (to[k]!=hson[v]&&to[k]!=fa[v])
dfs2(to[k],false);
}
void Change(int v,int x){
T.modify(1,1,n,pos[v],x);
}
void Qmax(int x,int y){
int res=-INF;
for (;top[x]!=top[y];x=fa[top[x]]){
if (deep[top[x]]<deep[top[y]]) x^=y^=x^=y;
upmax(res,T.qmax(1,1,n,pos[top[x]],pos[x]));
}
if (pos[x]>pos[y]) x^=y^=x^=y;
upmax(res,T.qmax(1,1,n,pos[x],pos[y]));
printf("%d\n",res);
}
void Qsum(int x,int y){
int res=0;
for (;top[x]!=top[y];x=fa[top[x]]){
if (deep[top[x]]<deep[top[y]]) x^=y^=x^=y;
res+=T.qsum(1,1,n,pos[top[x]],pos[x]);
}
if (pos[x]>pos[y]) x^=y^=x^=y;
res+=T.qsum(1,1,n,pos[x],pos[y]);
printf("%d\n",res);
}
char opt;
int main(){
freopen("ct.in","r",stdin);
freopen("ct.out","w",stdout);
n=getx();
rep(i,2,n) tjb(getx(),getx());
rep(i,1,n) w[i]=getx();
dfs1(1,0,0);dfs2(1,0);
q=getx();
rep(i,1,q){
for (opt=gt;opt!='H'&&opt!='M'&&opt!='S';opt=gt);
int x=getx(),y=getx();
if (opt=='H') Change(x,y);
if (opt=='M') Qmax(x,y);
if (opt=='S') Qsum(x,y);
}
}


树链剖分能做的LCT大概都能做吧。。

LCT常数不小就是了。但没爆栈风险。。囧

LCT还没写这题。囧
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: