树链剖分,先求出每个点的dfs序区间,查询时假设当前根为x,查询点为y,他们的dfs序分别为[xl,xr],[yl,yr],有三种情况,第一种x=y那么直接输出[1,n]的最小值,第二种这两个区间分离或者[xl,xr]包含[yl,yr],那么直接查询[yl,yr]的最小值,第三种[yl,yr]包含[xl,xr],找到x到y的路径上离y最近的点z,其区间为[zl,zr],那么需要输出min([1,zl-1],[zr+1,n])。
代码
1 #include<cstdio> 2 #include<algorithm> 3 #define N 2000010 4 using namespace std; 5 typedef long long ll; 6 int dp,pre[N],p[N],tt[N],f[N],gf[N],go[N]; 7 int L[N],R[N],tot,n,m,i,deep[N]; 8 int l[N],r[N],a,b,root,typ; 9 int jump[110000][19]; 10 ll value[N],e[N],c,v[N],s[N],inf; 11 void link(int x,int y) 12 { 13 dp++;pre[dp]=p[x];p[x]=dp;tt[dp]=y; 14 } 15 void dfs1(int x,int fa) 16 { 17 int i; 18 s[x]=1;f[x]=fa;deep[x]=deep[fa]+1; 19 jump[x][0]=fa;for (i=1;i<=17;i++) jump[x][i]=jump[jump[x][i-1]][i-1]; 20 i=p[x]; 21 while (i) 22 { 23 if (tt[i]!=fa) 24 { 25 dfs1(tt[i],x); 26 s[x]+=s[tt[i]]; 27 if (s[tt[i]]>s[go[x]]) go[x]=tt[i]; 28 } 29 i=pre[i]; 30 } 31 } 32 void dfs2(int x,int Fa,int fa) 33 { 34 int i=p[x]; 35 L[x]=++tot;gf[x]=Fa;e[tot]=value[x]; 36 if (go[x]) dfs2(go[x],Fa,x); 37 while (i) 38 { 39 if ((tt[i]!=fa)&&(tt[i]!=go[x])) 40 dfs2(tt[i],tt[i],x); 41 i=pre[i]; 42 } 43 R[x]=tot; 44 } 45 void build(int x,int a,int b) 46 { 47 l[x]=a;r[x]=b; 48 if (b-a>1) 49 { 50 int m=(l[x]+r[x])>>1; 51 build(2*x,a,m); 52 build(2*x+1,m,b); 53 s[x]=min(s[2*x],s[2*x+1]); 54 } 55 else 56 s[x]=e[b]; 57 } 58 void clean(int x) 59 { 60 if (v[x]) 61 { 62 s[x]=v[x]; 63 v[2*x]=v[x]; 64 v[2*x+1]=v[x]; 65 v[x]=0; 66 } 67 } 68 void change(int x,int a,int b,ll c) 69 { 70 clean(x); 71 if ((a<=l[x])&&(r[x]<=b)) 72 { 73 v[x]=c; 74 return; 75 } 76 int m=(l[x]+r[x])>>1; 77 if (a<m)change(2*x,a,b,c); 78 if (m<b)change(2*x+1,a,b,c); 79 clean(2*x);clean(2*x+1); 80 s[x]=min(s[2*x],s[2*x+1]); 81 } 82 ll query(int x,int a,int b) 83 { 84 clean(x); 85 if ((a<=l[x])&&(r[x]<=b)) 86 return s[x]; 87 int m; 88 ll ans=inf; 89 m=(l[x]+r[x])>>1; 90 if (a<m) ans=min(ans,query(2*x,a,b)); 91 if (m<b) ans=min(ans,query(2*x+1,a,b)); 92 return ans; 93 } 94 void gao(int a,int b,ll c) 95 { 96 while (1) 97 { 98 if (gf[a]==gf[b]) 99 { 100 if (deep[a]<deep[b]) a^=b^=a^=b; 101 change(1,L[b]-1,L[a],c); 102 return; 103 } 104 else 105 { 106 if (deep[gf[a]]<deep[gf[b]]) a^=b^=a^=b; 107 change(1,L[gf[a]]-1,L[a],c); 108 a=f[gf[a]]; 109 } 110 } 111 } 112 int find(int x,int y) 113 { 114 int i; 115 for (i=17;i>=0;i--) 116 if (deep[jump[x][i]]>deep[y]) x=jump[x][i]; 117 return x; 118 } 119 int main() 120 { 121 inf=1000000000;inf=inf*10; 122 scanf("%d%d",&n,&m); 123 for (i=1;i<n;i++) 124 { 125 scanf("%d%d",&a,&b); 126 link(a,b);link(b,a); 127 } 128 for (i=1;i<=n;i++) 129 scanf("%lld",&value[i]); 130 dfs1(1,0); 131 dfs2(1,1,0); 132 build(1,0,n); 133 scanf("%d",&root); 134 for (i=1;i<=m;i++) 135 { 136 scanf("%d",&typ); 137 if (typ==1) scanf("%d",&root); 138 else 139 if (typ==2) 140 { 141 scanf("%d%d%lld",&a,&b,&c); 142 gao(a,b,c); 143 } 144 else 145 { 146 scanf("%d",&a); 147 if (a==root) 148 printf("%lld\n",query(1,0,n)); 149 else 150 if ((L[a]<=L[root])&&(R[root]<=R[a])) 151 { 152 b=find(root,a); 153 c=inf; 154 if (L[b]-1>0) c=min(c,query(1,0,L[b]-1)); 155 if (R[b]<n) c=min(c,query(1,R[b],n)); 156 printf("%lld\n",c); 157 } 158 else 159 printf("%lld\n",query(1,L[a]-1,R[a])); 160 } 161 } 162 }
原文:http://www.cnblogs.com/fzmh/p/5424972.html