zoukankan      html  css  js  c++  java
  • CF150E Freezing with Style(点分治)

    CF150E Freezing with Style(点分治)

    题目描述

    给定一颗带边权的树,求一条边数在 ([L,R]) 之间的路径,并使得路径上边权的中位数最大。输出一条可行路径的两个端点。

    注:此处 (1,2,3,4) 的中位数为 (3) ,而非 (2) 或者 (2.5)

    数据范围

    (2 le l le r le n le 10^5)

    解题思路

    新技巧++

    首先二分,大于等于 mid 的设为 1,否则设为 -1,显然一条权值大于等于 0 的路径的中位数要大于等于 mid

    如何统计当前 -1,1 树的最大权路径,考虑点分治,分治过程中将 x 的所有子树按大小排序,二分最大中位数,然后一个子树算贡献,对于已扫过的子树建立单调队列,正在处理的子树来处理获得答案

    #include <queue>
    #include <vector>
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define MP make_pair
    #define ll long long
    #define fi first
    #define se second
    using namespace std;
    
    template <typename T>
    void read(T &x) {
        x = 0; bool f = 0;
        char c = getchar();
        for (;!isdigit(c);c=getchar()) if (c=='-') f=1;
        for (;isdigit(c);c=getchar()) x=x*10+(c^48);
        if (f) x=-x;
    }
    
    template<typename F>
    inline void write(F x)
    {
    	static short st[30];short tp=0;
    	if(x<0) putchar('-'),x=-x;
    	do st[++tp]=x%10,x/=10; while(x);
    	while(tp) putchar('0'|st[tp--]);
    	putchar('
    ');
    }
    
    template <typename T>
    inline void Mx(T &x, T y) { x < y && (x = y); }
    
    template <typename T>
    inline void Mn(T &x, T y) { x > y && (x = y); }
    
    const int N = 200500;
    const int inf = 1e8;
    int ne[N<<1], to[N<<1], w[N<<1], h[N], c[N], tot;
    inline void add(int x, int y, int z) {
    	ne[++tot] = h[x], to[h[x] = tot] = y, w[tot] = z;
    }
    
    int L, R, S, T, V;
    int siz[N], vis[N], Siz, lim, rt, s, t, n, m;
    void get(int x, int fa) {
    	siz[x] = 1; int mx = 0; 
    	for (int i = h[x]; i; i = ne[i]) {
    		int y = to[i]; if (vis[y] || y == fa) continue;
    		get(y, x), siz[x] += siz[y], Mx(mx, siz[y]);
    	}
    	Mx(mx, Siz - siz[x]);
    	if (mx < lim) rt = x, lim = mx;
    }
    
    struct node {
    	int a, b;
    }st[N];
    
    bool cmp(node a, node b) {
    	return siz[a.a] < siz[b.a];
    }
    
    int que[N], tmp[N], seq[N], sx[N], sqx[N], dep, tp, nw;
    void dfs(int x, int fa, int dp, int s, int F) {
    	if (tmp[dp] < s) tmp[dp] = s, sx[dp] = x; Mx(dep, dp);
    	for (int i = h[x]; i; i = ne[i]) {
    		int y = to[i]; if (y == fa || vis[y]) continue;
    		dfs(y, x, dp + 1, s + (w[i] >= F ? 1 : -1), F);  
    	}
    }
    
    bool check(int x, int F) {
    	seq[nw = 0] = 0, sqx[0] = x;
    	for (int a = 1;a <= tp; a++) {
    		int y = st[a].a; 
    		for (int i = 1;i <= siz[y]; i++) tmp[i] = -inf;
    		dep = 0, dfs(y, x, 1, st[a].b >= F ? 1 : -1, F);
    		int l = 0, r = -1, rb = nw;
    		for (int i = 1;i <= dep; i++) {
    			while (rb >= 0 && i + rb >= L) {
    				while (l <= r && seq[que[r]] <= seq[rb]) r--;
    				que[++r] = rb, rb--;
    			}
    			while (l <= r && que[l] + i > R) l++;
    			if (l <= r && seq[que[l]] + tmp[i] >= 0) 
    				return s = sqx[que[l]], t = sx[i], 1;
    		}
    		while (nw < dep) nw++, seq[nw] = -inf;
    		for (int i = 1;i <= dep; i++)
    			tmp[i] > seq[i] && (seq[i] = tmp[i], sqx[i] = sx[i]);
    	}
    	return 0;
    }
    
    void solve(int x) {
    	vis[x] = 1, get(x, 0), tp = 0;
    	for (int i = h[x]; i; i = ne[i]) {
    		int y = to[i]; if (vis[y]) continue;
    		st[++tp] = (node){y, w[i]};
    	}
    	sort(st + 1, st + tp + 1, cmp);
    	int l = V + 1, r = m; s = t = 0;
    	while (l <= r) {
    		int mid = (l + r) >> 1;
    		if (check(x, c[mid])) l = mid + 1;
    		else r = mid - 1;
    	}
    	if (r > V) check(x, c[r]), V = r, S = s, T = t;
    	for (int i = h[x]; i; i = ne[i]) {
    		int y = to[i]; if (vis[y]) continue;
    		lim = Siz = siz[y], rt = y, get(y, 0), solve(rt);
    	}
    }
    
    int main() {
    	read(n), read(L), read(R);
    	for (int i = 1, x, y, w;i < n; i++)
    		read(x), read(y), read(w), add(x, y, w), add(y, x, w), c[i] = w;
    	sort(c + 1, c + n), m = unique(c + 1, c + n) - c - 1;
    	rt = lim = Siz = n, get(1, 0), solve(rt);
    	printf ("%d %d
    ", S, T);
    	return 0;
    }
    
  • 相关阅读:
    mysql查看所有的数据库
    查看/杀死mysql进程
    PL/SQL 保存页面布局
    Linux 隐藏文件和目录,显示隐藏的文件和目录
    win10插入U盘多显示了一个盘符
    Linux安装rz和sz命令
    PL/SQL链接Oracle出现乱码
    解决Tomcat: Can't load IA 32-bit .dll on a AMD 64-bit platform问题
    Eclipse集成Tomcat的配置步骤实例
    搭建Eclipse+MyEclipse开发环境
  • 原文地址:https://www.cnblogs.com/Hs-black/p/13039328.html
Copyright © 2011-2022 走看看