SPOJ 375 query on a tree 树链剖分

题意:

给一棵树型数据结构

①支持修改边的权值      ②支持成段边权最值查询

树链剖分入门题、

 

树链剖分+线段树

用的notonlysuccess的线段树——不开结构体事先预处理的那种

我以前写的都是结构体的那种~

 

View Code
  1 #include <iostream>
  2 #include <algorithm>
  3 #include <cstdlib>
  4 #include <cstdio>
  5 #include <cstring>
  6 
  7 //notonlysuccess版线段树-树链剖分 
  8 
  9 #define N 20010
 10 
 11 using namespace std;
 12 
 13 int d[N][3];
 14 int to[N<<1],next[N<<1];
 15 int mx[N];
 16 int root,tot,cnt,n,m,cas;
 17 int head[N],dep[N],wnum[N],fa[N],top[N],son[N],sz[N];
 18 //sz[x]树的大小   dep[x]深度    top[x] x所在重路径中深度最小的点    fa[x]父亲节点   son[x]重儿子   wnum[x] x与其父亲之间的边的编号 
 19 
 20 inline void add(int u,int v)
 21 {
 22     to[cnt]=v; next[cnt]=head[u]; head[u]=cnt++;
 23 }
 24 
 25 inline void dfs(int x)//dfs求出fa[x],son[x],dep[x],sz[x] 
 26 {
 27     sz[x]=1; son[x]=0;
 28     for(int i=head[x];~i;i=next[i])
 29         if(fa[x]!=to[i])
 30         {
 31             fa[to[i]]=x;
 32             dep[to[i]]=dep[x]+1;
 33             dfs(to[i]);
 34             if(sz[to[i]]>sz[son[x]]) son[x]=to[i];//重边
 35             sz[x]+=sz[to[i]];
 36         }
 37 }
 38 
 39 inline void build(int x,int fx)//求出top[x],wnum[x](边的编号) 
 40 {
 41     wnum[x]=++tot; top[x]=fx;
 42     if(son[x]!=0) build(son[x],top[x]);//保证重边边权相连 
 43     for(int i=head[x];~i;i=next[i])
 44         if(to[i]!=son[x]&&to[i]!=fa[x]) build(to[i],to[i]);
 45 }
 46 
 47 inline void updata(int x,int lt,int rt,int wn,int w)
 48 {
 49     if(wn>rt||wn<lt) return;
 50     if(lt==rt) {mx[x]=w; return;}
 51     int mid=(lt+rt)>>1;
 52     int ls=x<<1,rs=ls+1;
 53     updata(ls,lt,mid,wn,w);
 54     updata(rs,mid+1,rt,wn,w);
 55     mx[x]=max(mx[ls],mx[rs]);
 56 }
 57 
 58 inline int maxlen(int x,int lt,int rt,int l,int r)//求边的编号在[l,r]之间的最大边权 
 59 {
 60     if(l>rt||r<lt) return 0;
 61     if(l<=lt&&rt<=r) return mx[x];
 62     int mid=(lt+rt)>>1;
 63     int ls=x<<1,rs=ls+1;
 64     return max(maxlen(ls,lt,mid,l,r),maxlen(rs,mid+1,rt,l,r));
 65 }
 66 
 67 inline int query(int x,int y)
 68 {
 69     int fx=top[x],fy=top[y],ans=0;
 70     while(fx!=fy)
 71     {
 72         if(dep[fx]<dep[fy]) swap(x,y),swap(fx,fy);
 73         ans=max(ans,maxlen(1,1,tot,wnum[fx],wnum[x]));
 74         x=fa[fx]; fx=top[x];
 75     }
 76     if(x==y) return ans;
 77     if(dep[x]>dep[y]) swap(x,y);
 78     return max(ans,maxlen(1,1,tot,wnum[son[x]],wnum[y]));
 79 }
 80 
 81 inline void read()
 82 {
 83     scanf("%d",&n);
 84     root=(n+1)>>1;
 85     fa[root]=dep[root]=cnt=tot=0;
 86     memset(sz,0,sizeof sz);
 87     memset(head,-1,sizeof head);
 88     memset(mx,0,sizeof mx);
 89     for(int i=1;i<n;i++)
 90     {
 91         scanf("%d%d%d",&d[i][0],&d[i][1],&d[i][2]);
 92         add(d[i][0],d[i][1]);
 93         add(d[i][1],d[i][0]);
 94     }
 95     dfs(root);
 96     build(root,root);
 97     for(int i=1;i<n;i++)
 98     {
 99         if(dep[d[i][0]]>dep[d[i][1]]) swap(d[i][0],d[i][1]);
100         updata(1,1,tot,wnum[d[i][1]],d[i][2]);
101     }
102 }
103 
104 inline void go()
105 {
106     char str[10]; int a,b;
107     while(true)
108     {
109         scanf("%s",str);
110         if(str[0]=='D') return;
111         scanf("%d%d",&a,&b);
112         if(str[0]=='Q') printf("%d\n",query(a,b));
113         else updata(1,1,tot,wnum[d[a][1]],b);
114     }
115 }
116 
117 int main()
118 {
119     scanf("%d",&cas);
120     while(cas--) read(),go();
121     return 0;
122 } 

 

又写了一发,和之前风格完全不同。。

 

View Code
  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdlib>
  4 #include <cstdio>
  5 #include <algorithm>
  6 
  7 #define N 100000
  8 #define M 200000
  9 #define INF 1e9
 10 
 11 using namespace std;
 12 
 13 int head[N],next[M],to[M],len[M];
 14 int son[N],fa[N],dat[M],bh[M],pre[N],dep[N],sz[N],top[N];
 15 int q[N],mx[M<<2];
 16 int n,cnt,tot;
 17 
 18 inline void add(int u,int v,int w)
 19 {
 20     to[cnt]=v; len[cnt]=w; next[cnt]=head[u]; head[u]=cnt++;
 21 }
 22 
 23 inline void init()
 24 {
 25     memset(son,-1,sizeof son);
 26     memset(fa,0,sizeof fa);
 27     memset(head,-1,sizeof head); cnt=0;
 28     tot=0;
 29 }
 30 
 31 inline void prep()
 32 {
 33     int h=1,t=2,sta;
 34     q[1]=1; dep[1]=1;
 35     while(h<t)
 36     {
 37         sta=q[h++]; sz[sta]=1;
 38         for(int i=head[sta];~i;i=next[i])
 39             if(fa[sta]!=to[i])
 40             {
 41                 fa[to[i]]=sta;
 42                 dep[to[i]]=dep[sta]+1;
 43                 pre[to[i]]=len[i];
 44                 q[t++]=to[i];
 45             }
 46     }
 47     for(int j=t-1;j>=1;j--)
 48     {
 49         sta=q[j];
 50         for(int i=head[sta];~i;i=next[i])
 51             if(fa[sta]!=to[i])
 52             {
 53                 sz[sta]+=sz[to[i]];
 54                 if(son[sta]==-1||sz[to[i]]>sz[to[son[sta]]]) son[sta]=i;
 55             }
 56     }
 57     for(int i=1;i<t;i++)
 58     {
 59         sta=q[i];
 60         if(to[son[fa[sta]]]==sta) top[sta]=top[fa[sta]];
 61         else top[sta]=sta;
 62     }
 63 }
 64 
 65 inline void rewrite()
 66 {
 67     for(int i=1;i<=n;i++)
 68         if(top[i]==i)
 69             for(int j=son[i];~j;j=son[to[j]])
 70             {
 71                 bh[(j>>1)+1]=++tot;
 72                 dat[tot]=len[i];
 73             }
 74 }
 75 
 76 inline void pushup(int u)
 77 {
 78     mx[u]=max(mx[u<<1],mx[u<<1|1]);
 79 }
 80 
 81 inline void build(int u,int L,int R)
 82 {
 83     if(L==R) {mx[u]=dat[L];return;}
 84     int MID=(L+R)>>1;
 85     build(u<<1,L,MID); build(u<<1|1,MID+1,R);
 86     pushup(u);
 87 }
 88 
 89 inline void read()
 90 {
 91     init();
 92     scanf("%d",&n);
 93     for(int i=1,a,b,c;i<n;i++)
 94     {
 95         scanf("%d%d%d",&a,&b,&c);
 96         add(a,b,c); add(b,a,c);
 97     }
 98     
 99     prep();
100     rewrite();
101     build(1,1,tot);
102 }
103 
104 inline void updata(int u,int L,int R,int pos,int sp)
105 {
106     if(L==R) {mx[u]=sp;return;}
107     int MID=(L+R)>>1;
108     if(pos<=MID) updata(u<<1,L,MID,pos,sp);
109     else updata(u<<1|1,MID+1,R,pos,sp);
110     pushup(u);
111 }
112 
113 inline int querymax(int u,int L,int R,int l,int r)
114 {
115     if(l<=L&&R<=r) return mx[u];
116     int MID=(L+R)>>1,res=-INF;
117     if(l<MID) res=max(res,querymax(u<<1,L,MID,l,r));
118     if(MID<r) res=max(res,querymax(u<<1|1,MID+1,R,l,r));
119     return res;
120 }
121 
122 inline int getmax(int x,int y)
123 {
124     int res=-INF;
125     while(top[x]!=top[y])
126     {
127         if(dep[top[x]]<dep[top[y]]) swap(x,y);
128         res=max(res,querymax(1,1,tot,bh[top[x]],bh[x]));
129         res=max(res,pre[top[x]]);
130         x=fa[top[x]];
131     }
132     if(bh[x]>bh[y]) swap(x,y);
133     res=max(res,querymax(1,1,tot,bh[x],bh[y]));
134     return res;
135 }
136 
137 inline void go()
138 {
139     char str[10];int a,b;
140     while(scanf("%s",str))
141     {
142         if(str[0]=='D') break;
143         scanf("%d%d",&a,&b);
144         if(str[0]=='C') updata(1,1,tot,bh[a],b);
145         else printf("%d\n",getmax(a,b));
146     }
147 }
148 
149 int main()
150 {
151     int cas;scanf("%d",&cas);
152     while(cas--) read(),go();
153     return 0;
154 }

 

 

 

posted @ 2013-01-02 23:52  proverbs  阅读(307)  评论(0编辑  收藏  举报