zoukankan      html  css  js  c++  java
  • [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
     */
    
  • 相关阅读:
    Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException
    idea 设置svn忽略 .idea内的文件
    使用JDBC连接MySql时出现:The server time zone value '�й���׼ʱ��' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration
    问题:SpringBoot访问不到Controller
    JAVA 并发编程-多个线程之间共享数据
    Data时间格式化
    wow.js中各种特效对应的类名(滚动效果)
    [从零开始搭网站七]CentOS上安装Mysql
    [从零开始搭网站六]为域名申请免费SSL证书(https),并为Tomcat配置https域名所用的多SSL证书
    [从零开始搭网站五]http网站Tomcat配置web.xml和server.xml
  • 原文地址:https://www.cnblogs.com/mrclr/p/10772257.html
Copyright © 2011-2022 走看看