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

来源:互联网 发布:守望先锋笔记本优化 编辑:程序博客网 时间:2024/05/01 11:20

树链剖分网上的资料比较详细了。


其实我一直很怕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,rinline 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);elsemodify(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还没写这题。囧

0 0
原创粉丝点击