[WC2010]重建计划

嘟嘟嘟


要不这篇博客我水一下?


思路很显然,点分治+01分数规划+单调队列。
但就是难写。
点分治的时候我们把每一个点到重心这条链按深度排序,然后对于每一个点的链就有一个连续深度的区间可以和这条链拼上,因为要找一条权值大于(0)的链,那就相当于找这个区间的最大值。然后随着点深度递增,这个区间就不断向左移,就成了滑动窗口了。
细节就看shadowice1984的题解啦!


我写的时候没有把点分树建出来,只记录了重心序列,因为重心是按dfs序找的,所以只要每次用完后标记,就不会出问题,还省去了递归。

#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
#define enter puts("") 
#define space putchar(' ')
#define Mem(a, x) memset(a, x, sizeof(a))
#define In inline
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-8;
const int maxn = 1e6 + 5;
inline ll read()
{
  ll ans = 0;
  char ch = getchar(), last = ' ';
  while(!isdigit(ch)) last = ch, ch = getchar();
  while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
  if(last == '-') ans = -ans;
  return ans;
}
inline void write(ll x)
{
  if(x < 0) x = -x, putchar('-');
  if(x >= 10) write(x / 10);
  putchar(x % 10 + '0');
}

int n, LL, RR;
struct Edge
{
  int nxt, to; ll w;
}e[maxn << 1];
int head[maxn], ecnt = -1;
In void addEdge(int x, int y, ll w)
{
  e[++ecnt] = (Edge){head[x], y, w};
  head[x] = ecnt;
}

int pos[maxn], pcnt = 0;

bool out[maxn];
int cg, Siz, siz[maxn], Max[maxn];
In void dfs0(int now, int _f, int& cg)
{
  siz[now] = Max[now] = 1;
  for(int i = head[now], v; ~i; i = e[i].nxt)
    {
      if((v = e[i].to) == _f || out[v]) continue;
      dfs0(v, now, cg);
      siz[now] += siz[v];
      Max[now] = max(Max[now], siz[v]);
    }
  Max[now] = max(Max[now], Siz - siz[now]);
  if(!cg || Max[cg] > Max[now]) cg = now;
}
In void dfs(int now)
{
  cg = 0;
  dfs0(now, 0, cg);
  pos[++pcnt] = cg;
  out[cg] = 1;
  for(int i = head[cg], v; ~i; i = e[i].nxt)
    if(!out[v = e[i].to]) Siz = siz[v], dfs(v);
}

struct Node
{
  int id, val; db w;
  In bool operator < (const Node& oth)const
  {
    return val < oth.val;
  }
}t[maxn], q[maxn];
In void dfs_dep(int now, int _f, int dep, int& Max)
{
  if(dep > Max) Max = dep;
  for(int i = head[now], v; ~i; i = e[i].nxt)
    if((v = e[i].to) != _f && !out[v]) dfs_dep(v, now, dep + 1, Max);
}
db b[maxn], dis[maxn], mid, ans;
In void dfs_dis(int now, int _f, int dep, db d)
{
  dis[dep] = max(dis[dep], d);
  for(int i = head[now], v; ~i; i = e[i].nxt)
    if((v = e[i].to) != _f && !out[v]) dfs_dis(v, now, dep + 1, d + e[i].w - mid);
}
int L, R, hd, tl, tcnt = 0;
In void solve()
{
  for(int id = 1; id <= pcnt; ++id)
    {
      tcnt = 0;
      for(int i = head[pos[id]], v; ~i; i = e[i].nxt)
	{
	  if(out[v = e[i].to]) continue;
	  int Max = 0;
	  dfs_dep(v, pos[id], 1, Max);
	  t[++tcnt] = (Node){v, Max, (db)e[i].w - mid};
	}
      sort(t + 1, t + tcnt + 1);
      for(int i = 1; i <= t[tcnt].val; ++i) b[i] = -INF;
      for(int i = 1; i <= tcnt; ++i)
	{
	  for(int j = 1; j <= t[i].val; ++j) dis[j] = -INF;
	  dfs_dis(t[i].id, pos[id], 1, t[i].w);
	  if(i ^ 1)
	    {
	      L = max(1, LL - t[i].val), R = max(0, min(t[i - 1].val, RR - t[i].val)), hd = 1, tl = 0;
	      for(int j = L; j <= R; ++j)
		{
		  while(hd <= tl && q[tl].w < b[j]) --tl;
		  q[++tl] = (Node){j, 0, b[j]};
		}
	      for(int j = min(RR, t[i].val); j >= max(1, LL - t[i - 1].val); --j)
		{
		  while(hd <= tl && q[hd].id + j < LL) ++hd;
		  if(R + 1 <= t[i - 1].val && R + 1 + j <= RR)
		    {
		      ++R;
		      while(hd <= tl && q[tl].w < b[R]) --tl;
		      q[++tl] = (Node){R, 0, b[R]};
		    }
		  if(hd <= tl) ans = max(ans, q[hd].w + dis[j]);
		  if(ans > 0) return;
		}
	    }
	  for(int j = 1; j <= t[i].val; ++j) b[j] = max(b[j], dis[j]);
	}
      out[pos[id]] = 1;
    }
}

int main()
{
  Mem(head, -1);
  n = read(); LL = read(), RR = read();
  for(int i = 1; i < n; ++i)
    {
      int x = read(), y = read(); ll w = read();
      addEdge(x, y, w), addEdge(y, x, w);
    }
  Siz = n; dfs(1);
  db L = 0, R = 1e6;
  for(int t = 1; t <= 35; ++t)
    {
      mid = (L + R + eps) * 0.5;
      ans = -INF; Mem(out, 0);
      solve();
      if(ans > eps) L = mid;
      else R = mid - eps;
    }
  printf("%.3lf
", L);
  return 0;
}
/*
8
2 4
1 2 3
1 4 4
3 2 4
3 5 6
6 2 9
6 8 2
2 7 4
 */
原文地址:https://www.cnblogs.com/mrclr/p/10772257.html