题意:
给一棵树型数据结构
①支持修改边的权值 ②支持成段边权最值查询
树链剖分入门题、
树链剖分+线段树
用的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 }