【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 }

 

posted on 2017-03-13 15:38  myx12345  阅读(198)  评论(0编辑  收藏  举报

导航