【BZOJ1758】重建计划(点分治,长链剖分,线段树)
题意:
给定一棵n个点的树,每条边有权值。
求一条链,这条链包含的边数在L和U之间,且平均边权最大。
N﹤=100000
思路:
做法一:RYZ作业
二分答案再点分治,寻找是否有大于0且边数在L和U之间的链
f[i]为当前子树深度为i的链最大总和,g[i]为前几个深度为i的链最大总和
维护一个下标递增,值递增的单调队列
按子树深度排序一定要加,因为清空与当前子树深度最大值有关,不加的话可能会退化成n^2
改了快一天改不出,还加了迭代,最后发现是分治的时候root打成v,相当于什么都没干……
1 var head,vet,next,c,d,size,flag,q1:array[1..210000]of longint; 2 p:array[0..210000]of longint; 3 len,h,q2:array[1..210000]of double; 4 f,g:array[0..210000]of double; 5 n,i,tot,root,l1,r1,sum,mx,mxdep,x,y,z,tmp,t,w,now,m:longint; 6 eps,oo,mid:double; 7 8 procedure swap(var x,y:longint); 9 var t:longint; 10 begin 11 t:=x; x:=y; y:=t; 12 end; 13 14 function max(x,y:longint):longint; 15 begin 16 if x>y then exit(x); 17 exit(y); 18 end; 19 20 function min(x,y:longint):longint; 21 begin 22 if x<y then exit(x); 23 exit(y); 24 end; 25 26 procedure add(a,b,c:longint); 27 begin 28 inc(tot); 29 next[tot]:=head[a]; 30 vet[tot]:=b; 31 len[tot]:=c; 32 head[a]:=tot; 33 end; 34 35 procedure getroot(u,fa:longint); 36 var e,v:longint; 37 begin 38 size[u]:=1; p[u]:=0; 39 e:=head[u]; 40 while e<>0 do 41 begin 42 v:=vet[e]; 43 if (v<>fa)and(flag[v]=0) then 44 begin 45 getroot(v,u); 46 size[u]:=size[u]+size[v]; 47 p[u]:=max(p[u],size[v]); 48 end; 49 e:=next[e]; 50 end; 51 p[u]:=max(p[u],sum-p[u]); 52 if p[u]<p[root] then root:=u; 53 end; 54 55 procedure dfs(u,fa,dep:longint;t:double); 56 var e,v:longint; 57 begin 58 if f[dep]<t then f[dep]:=t; 59 mx:=max(mx,dep); 60 e:=head[u]; 61 while e<>0 do 62 begin 63 v:=vet[e]; 64 if (v<>fa)and(flag[v]=0) then dfs(v,u,dep+1,t+len[e]-mid); 65 e:=next[e]; 66 end; 67 68 end; 69 70 procedure ins(k:longint;x:double); 71 begin 72 while (w>=t)and(q2[w]<x) do dec(w); 73 inc(w); q1[w]:=k; q2[w]:=x; 74 end; 75 76 procedure del(k:longint); 77 begin 78 while (t<=w)and(q1[t]>=k) do inc(t); 79 end; 80 81 procedure getdep(u,fa,dep:longint); 82 var e,v:longint; 83 begin 84 e:=head[u]; 85 if dep>d[m] then d[m]:=dep; 86 while e<>0 do 87 begin 88 v:=vet[e]; 89 if (v<>fa)and(flag[v]=0) then getdep(v,u,dep+1); 90 e:=next[e]; 91 end; 92 end; 93 94 procedure qsort(l,r:longint); 95 var i,j,mid:longint; 96 t:double; 97 begin 98 i:=l; j:=r; mid:=d[(l+r)>>1]; 99 repeat 100 while mid>d[i] do inc(i); 101 while mid<d[j] do dec(j); 102 if i<=j then 103 begin 104 swap(d[i],d[j]); 105 swap(c[i],c[j]); 106 t:=h[i]; h[i]:=h[j]; h[j]:=t; 107 inc(i); dec(j); 108 end; 109 until i>j; 110 if l<j then qsort(l,j); 111 if i<r then qsort(i,r); 112 end; 113 114 function solve(u:longint;avg:double):double; 115 var t1,t2,ans,tmp:double; 116 v,e,i,j:longint; 117 begin 118 t1:=avg; t2:=-oo; 119 m:=0; 120 e:=head[u]; 121 while e<>0 do 122 begin 123 v:=vet[e]; 124 if flag[v]=0 then 125 begin 126 inc(m); 127 getdep(v,u,1); 128 c[m]:=v; h[m]:=len[e]; 129 end; 130 e:=next[e]; 131 end; 132 if m>0 then qsort(1,m); 133 while t1-t2>eps do 134 begin 135 t2:=t1; mid:=t1; ans:=-oo; 136 mxdep:=0; g[0]:=0; 137 for j:=1 to m do 138 begin 139 v:=c[j]; 140 mx:=0; 141 dfs(v,u,1,h[j]-mid); 142 t:=1; w:=0; 143 for i:=min(mxdep,r1) to l1 do ins(i,g[i]); 144 for i:=max(1,l1-mxdep) to mx do 145 begin 146 if l1-i>=0 then ins(l1-i,g[l1-i]); 147 del(r1-i+1); 148 if t<=w then 149 if (f[i]+q2[t])/(q1[t]+i)>ans then 150 ans:=(f[i]+q2[t])/(q1[t]+i); 151 end; 152 mxdep:=max(mxdep,mx); 153 for i:=0 to mx do 154 if f[i]>g[i] then g[i]:=f[i]; 155 for i:=0 to mx do f[i]:=-oo; 156 end; 157 for i:=0 to mxdep do g[i]:=-oo; 158 t1:=t1+ans; 159 end; 160 flag[u]:=1; t2:=t1; 161 e:=head[u]; 162 while e<>0 do 163 begin 164 v:=vet[e]; 165 if flag[v]=0 then 166 begin 167 root:=0; sum:=size[v]; 168 getroot(v,0); 169 tmp:=solve(root,t1); 170 if tmp>t2 then t2:=tmp; 171 end; 172 e:=next[e]; 173 end; 174 exit(t2); 175 176 end; 177 178 begin 179 assign(input,'bzoj1758.in'); reset(input); 180 assign(output,'bzoj1758.out'); rewrite(output); 181 readln(n); 182 readln(l1,r1); 183 oo:=1e8; 184 for i:=1 to n-1 do 185 begin 186 readln(x,y,z); 187 add(x,y,z); 188 add(y,x,z); 189 end; 190 p[0]:=n+1; root:=0; sum:=n; 191 eps:=1e-4; 192 getroot(1,0); 193 for i:=0 to n do 194 begin 195 f[i]:=-oo; g[i]:=-oo; 196 end; 197 writeln(solve(root,0):0:3); 198 close(input); 199 close(output); 200 end.
做法2:From https://blog.bill.moe/WC2010-rebuild/
建立一个答案表,顺序是长链剖分的dfs序
长链可以共用答案表,轻儿子暴力合并到父亲所在长链中
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 typedef unsigned int uint; 5 typedef unsigned long long ull; 6 typedef pair<int,int> PII; 7 typedef pair<ll,ll> Pll; 8 typedef vector<int> VI; 9 typedef vector<PII> VII; 10 typedef pair<ll,int>P; 11 #define N 200010 12 #define M 200010 13 #define fi first 14 #define se second 15 #define MP make_pair 16 #define pi acos(-1) 17 #define mem(a,b) memset(a,b,sizeof(a)) 18 #define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++) 19 #define per(i,a,b) for(int i=(int)a;i>=(int)b;i--) 20 #define lowbit(x) x&(-x) 21 #define Rand (rand()*(1<<16)+rand()) 22 #define id(x) ((x)<=B?(x):m-n/(x)+1) 23 #define ls p<<1 24 #define rs p<<1|1 25 26 const ll MOD=1e9+7,inv2=(MOD+1)/2; 27 double eps=1e-4; 28 int INF=1<<30; 29 ll inf=5e13; 30 int dx[4]={-1,1,0,0}; 31 int dy[4]={0,0,-1,1}; 32 33 double t[N<<2]; 34 int head[N],vet[N],len[N],nxt[N], 35 dep[N],son[N],slen[N],fa[N],id[N],dfn[N],mx[N],top[N], 36 tot,L,R,tim,n; 37 double ans,tmp[N]; 38 39 int read() 40 { 41 int v=0,f=1; 42 char c=getchar(); 43 while(c<48||57<c) {if(c=='-') f=-1; c=getchar();} 44 while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar(); 45 return v*f; 46 } 47 48 void add(int a,int b,int c) 49 { 50 nxt[++tot]=head[a]; 51 vet[tot]=b; 52 len[tot]=c; 53 head[a]=tot; 54 } 55 56 void build(int l,int r,int p) 57 { 58 t[p]=-1e18; 59 if(l==r) 60 { 61 id[l]=p; 62 return; 63 } 64 int mid=(l+r)>>1; 65 build(l,mid,ls); 66 build(mid+1,r,rs); 67 } 68 69 void update(int u,double v) 70 { 71 int now=id[u]; 72 while(now) 73 { 74 t[now]=max(t[now],v); 75 now>>=1; 76 } 77 } 78 79 double query(int l,int r,int x,int y,int p) 80 { 81 if(x<=l&&r<=y) return t[p]; 82 int mid=(l+r)>>1; 83 double res=-1e18; 84 if(x<=mid) res=max(res,query(l,mid,x,y,ls)); 85 if(y>mid) res=max(res,query(mid+1,r,x,y,rs)); 86 return res; 87 } 88 89 void dfs1(int u,int pre,int d) 90 { 91 dep[u]=mx[u]=d; 92 fa[u]=pre; 93 int e=head[u]; 94 while(e) 95 { 96 int v=vet[e]; 97 if(v!=pre) 98 { 99 dfs1(v,u,d+1); 100 if(mx[v]>mx[son[u]]) 101 { 102 son[u]=v; 103 slen[u]=len[e]; 104 mx[u]=mx[v]; 105 } 106 } 107 e=nxt[e]; 108 } 109 } 110 111 void dfs2(int u,int ance) 112 { 113 top[u]=ance; 114 dfn[u]=++tim; 115 if(son[u]) dfs2(son[u],ance); 116 int e=head[u]; 117 while(e) 118 { 119 int v=vet[e]; 120 if(v!=fa[u]&&v!=son[u]) dfs2(v,v); 121 e=nxt[e]; 122 } 123 } 124 125 double ask(int u,int l,int r) 126 { 127 l=max(l,0); 128 r=min(r,mx[u]-dep[u]); 129 if(l>r) return -1e18; 130 return query(1,n,dfn[u]+l,dfn[u]+r,1); 131 } 132 133 void solve(int u,double d,double mid) 134 { 135 update(dfn[u],d); 136 if(son[u]) solve(son[u],d+slen[u]-mid,mid); 137 int e=head[u]; 138 while(e) 139 { 140 int v=vet[e]; 141 if(v!=fa[u]&&v!=son[u]) 142 { 143 solve(v,d+len[e]-mid,mid); 144 rep(j,1,mx[v]-dep[v]+1) 145 { 146 tmp[j]=t[id[dfn[v]+j-1]]; 147 ans=max(ans,tmp[j]+ask(u,L-j,R-j)-2*d); 148 } 149 rep(j,1,mx[v]-dep[v]+1) update(dfn[u]+j,tmp[j]); 150 } 151 e=nxt[e]; 152 } 153 ans=max(ans,ask(u,L,R)-d); 154 } 155 156 int isok(double K) 157 { 158 build(1,n,1); 159 ans=-1e18; 160 solve(1,0,K); 161 return ans>=-eps; 162 } 163 164 int main() 165 { 166 n=read(),L=read(),R=read(); 167 tot=0; 168 rep(i,1,n-1) 169 { 170 int x=read(),y=read(),z=read(); 171 add(x,y,z); 172 add(y,x,z); 173 } 174 dfs1(1,0,1); 175 tim=0; 176 dfs2(1,1); 177 double left=0,right=1e10; 178 while(right-left>eps) 179 { 180 double mid=(left+right)/2; 181 if(isok(mid)) left=mid; 182 else right=mid; 183 } 184 printf("%.3f\n",left); 185 return 0; 186 }
null