树链剖分

来源:互联网 发布:井柏然毁了肖奈 知乎 编辑:程序博客网 时间:2024/06/06 07:46

人生中第一道树链剖分的题目,写个博客记念一下...(参考博客:http://blog.csdn.net/y990041769/article/details/40348013 )

#include<iostream>#include<cstdio>#include<cstring>#include<vector>#define lson o*2#define rson o*2+1using namespace std;int son[10005],deep[10005],fa[10005],id[10005],size[10005],top[10005],val[10005];struct date {int first;int from;int nxt;int w;int to;};struct kk {int dis;};date a[40000];date cc[40000];kk b[40000];int n,num,numm,tot;void add(int l,int r,int dis) {a[++num].to=r;a[num].w=dis;a[num].nxt=a[l].first;a[num].from=l;a[l].first=num;}void dfs1(int u,int f,int d) {deep[u]=d;son[u]=0;  //big sonsize[u]=1;fa[u]=f;  //fatherfor(int i=a[u].first; i; i=a[i].nxt) {int x=a[i].to;if(x==f) continue;else dfs1(x,u,d+1);size[u]+=size[x];if(size[son[u]]<size[x])son[u]=x;}} //找重儿子 void dfs2(int x,int t) {top[x]=t;id[x]=++tot;if(son[x])  dfs2(son[x],t); //如果有重儿子,跳(处理重边)for(int i=a[x].first; i ; i=a[i].nxt) {int u=a[i].to;if(u==fa[x]||u==son[x]) continue;dfs2(u,u); //处理轻边}} //重儿子连成重边与重链 void build(int l,int r,int o) {if(l==r) {b[o].dis=val[l];return;}int mid=(l+r)/2;build(l,mid,lson);build(mid+1,r,rson);b[o].dis=max(b[lson].dis,b[rson].dis);}void update(int o,int l,int r,int mu,int k) {if(l==r) {b[o].dis=k;return;}int mid=(l+r)/2;if(mu<=mid) update(lson,l,mid,mu,k);else update(rson,mid+1,r,mu,k);b[o].dis=max(b[lson].dis,b[rson].dis);}int query(int o,int l,int r,int ll,int rr) {if(l>=ll&&r<=rr) {return b[o].dis;}int mid=(l+r)/2,ans=0;if(ll<=mid)   ans=max(ans,query(lson,l,mid,ll,rr));if(rr>mid)  ans=max(ans,query(rson,mid+1,r,ll,rr));return ans;}int TT(int l,int r) {int tp1=top[l],tp2=top[r],ans=0;while(tp1!=tp2) {if (deep[tp1]<deep[tp2]) {swap(tp1,tp2);swap(l,r);}ans=max(query(1,1,tot,id[tp1],id[l]) , ans);l=fa[tp1];tp1=top[l];}if(l==r) return ans;if(deep[l]>deep[r]) swap(l,r);ans=max(query(1,1,n,id[son[l]],id[r]),ans);return ans;}int main() {scanf("%d",&n);for(int i=1; i<n; i++) {int x,y,dis;scanf("%d%d%d",&x,&y,&dis);cc[i].from=x;cc[i].to=y;cc[i].w=dis;add(x,y,dis);add(y,x,dis);}dfs1(1,0,1);dfs2(1,1);for(int i=1; i<n; i++) {if(deep[cc[i].from]<=deep[cc[i].to])   val[id[cc[i].to]]=cc[i].w;else val[id[cc[i].from]]=cc[i].w;}//边权加到较深的点中去build(1,tot,1);char c[100];while(scanf("%s",c)&&c[0]!='D') {int x,y;if(c[0]=='C') {scanf("%d%d",&x,&y);int k=max(id[cc[x].from],id[cc[x].to]); //importantupdate(1,1,tot,k,y);}  else {scanf("%d%d",&x,&y);printf("%d\n",TT(x,y));}}return 0;}

这代码...整整调了我差不多一整天...

3 0