【Codeforces150E】Freezing with Style

来源:互联网 发布:网络信用卡有哪些 编辑:程序博客网 时间:2024/06/05 18:56

题意:求树上路径长度在[L,R]之间的中位数最大的路径(长度为偶数取后面(较大)那个)。

显然需要二分mid,然后val>=mid的边赋值为1,否则赋值为-1。问题转化为树上是否存在路径长度在[L,R]的路径路径和大于等于零。
这个可以树分治。每条路径都并定在某层的重心。所以考虑怎么求出rt的不同子树中,是否存在两点满足要求。
第一想法是按某种顺序枚举子树,然后通过线段树维护深度确定的到rt路径和最大值。然而这样是O(nlog3n)的(然而我一开始没有意识到,斯波地撕烤了很久为什么T了)。
所以就有一种神奇方法:
按从小到大(深度或者子树大小)枚举子树,然后每将一颗子树更新进到数组前,用双指针队列扫描。
类似于启发式合并的方法,会发现这样是每步均摊O(1),所以总复杂度是O(nlog2n)
(是不是感觉是一道斯波题??然而我写的时间跟代码长度都破天际了啊。。。)
附图:
真的心累
真的心累!!!

#include <bits/stdc++.h>#define gc getchar()#define ll long long#define mid (l+r>>1)#define N 100009#define inf 0x3f3f3f3fusing namespace std;int n, LL, RR, first[N], number = 1, sz[N], fa[N], Max[N];int len, now_x, now_y, Ans_x, Ans_y, SZ[N], Ans = -1, deep[N];vector<int> go[N];struct edge{    int to, next, val, vis;    void add(int x, int y, int z)    {        to = y, next = first[x], first[x] = number, val = z;    }    int v(int lim)    {        return val >= lim ? 1 : -1;    }}e[N << 1];struct node{    int val, pos;    node(int val = 0, int pos = 0) :val(val), pos(pos) {}    bool operator <(const node &rhs) const    {        return val < rhs.val;    }    bool operator <=(const node &rhs) const    {        return val <= rhs.val;    }}Max_val[N << 2];bool cmp(int x, int y){    return SZ[e[x].to] < SZ[e[y].to];}node max(const node &A, const node &B){    return A < B ? B : A;}int read(){    int x = 1;    char ch;    while (ch = gc, ch<'0' || ch>'9') if (ch == '-') x = -1;    int s = ch - '0';    while (ch = gc, ch >= '0'&&ch <= '9') s = s * 10 + ch - '0';    return x*s;}void Get_G(int x, int y, int &G){    sz[x] = 1, Max[x] = 0;    for (int i = first[x]; i; i = e[i].next)        if (!e[i].vis&&e[i].to != fa[x])        {            Get_G(e[i].to, y, G);            sz[x] += sz[e[i].to];            Max[x] = max(Max[x], sz[e[i].to]);        }    Max[x] = max(Max[x], y - sz[x]);    if (Max[x] < Max[G]) G = x;}node Q[N << 1], q[N << 1];int pos[N << 1];void Dfs(int G, int y, int x, int last, int sum, int depth, int lim){    q[depth] = max(q[depth], node(sum, x));    if (depth >= LL&&depth <= RR&&sum >= 0)    {        now_x = x, now_y = G;        return;    }    for (int i = first[x]; i; i = e[i].next)        if (e[i].to != last && !e[i].vis)        {            Dfs(G, y, e[i].to, x, sum + e[i].v(lim), depth + 1, lim);            if (now_x&&now_y) return;        }}bool check(int G, int tmp, int y, int lim){    for (int i = 1; i <= y; i++) Q[i] = node(-inf, 0);    now_x = now_y = 0;    for (int i = 0; i < go[G].size(); i++)        if (!e[go[G][i]].vis)        {            int sz_now = 0;            if (go[G][i] == tmp) sz_now = y - sz[G];            else sz_now = sz[e[go[G][i]].to];            for (int j = 1; j <= sz_now; j++) q[j] = node(-inf, 0);            Dfs(G, y, e[go[G][i]].to, G, e[go[G][i]].v(lim), 1, lim);            if (now_x&&now_y) return true;            int head = 1, tail = 0, r = max(1, LL - sz_now);            pos[tail] = 0;            for (int j = sz_now; j; j--)            {                while (r + j <= RR&&node(-inf, 0) < Q[r]&&r <= y)                {                    while (head <= tail&&Q[pos[tail]] <= Q[r]) tail--;                    pos[++tail] = r++;                }                while (head <= tail&&pos[head] + j < LL) head++;                if (head <= tail&&Q[pos[head]].val + q[j].val >= 0&&pos[head] + j >= LL&&pos[head] + j <=RR)                {                    now_x = Q[pos[head]].pos;                    now_y = q[j].pos;                    return true;                }            }            for (int j = 1; j <= sz_now; j++)                Q[j] = max(Q[j], q[j]);        }    return false;}void solve(int x, int y){    int G = 0;    Get_G(x, y, G);    int tmp = 0;    for (int i = first[G]; i; i = e[i].next)        if (e[i].to == fa[G]) tmp = i;    int l = 0, r = inf, ret = 0, ret_x = 0, ret_y = 0;    while (l<=r)    {        if (check(G, tmp, y, mid)) ret_x = now_x, ret_y = now_y, ret = mid, l = mid + 1;        else r = mid - 1;    }    if (ret > Ans)    {        Ans = ret;        Ans_x = ret_x;        Ans_y = ret_y;    }    if (tmp && !e[tmp].vis)    {        e[tmp].vis = e[tmp ^ 1].vis = 1;        solve(x, y - sz[G]);    }    for (int i = first[G]; i; i = e[i].next)        if (!e[i].vis)        {            e[i].vis = e[i ^ 1].vis = 1;            solve(e[i].to, sz[e[i].to]);        }}void dfs(int x){    SZ[x] = 1;    deep[x] = deep[fa[x]] + 1;    for (int i = first[x]; i; i = e[i].next)    {        if (e[i].to != fa[x]) fa[e[i].to] = x, dfs(e[i].to), SZ[x] += SZ[e[i].to];        go[x].push_back(i);    }    int tmp = SZ[fa[x]];    SZ[fa[x]] = n - SZ[x];    sort(go[x].begin(), go[x].end(), cmp);    SZ[fa[x]] = tmp;}int main(){    Max[0] = inf;    n = read(), LL = read(), RR = read();    for (int i = 1; i < n; i++)    {        int x = read(), y = read(), z = read();        e[++number].add(x, y, z), e[++number].add(y, x, z);    }    dfs(1);    solve(1, n);    printf("%d %d\n", Ans_x, Ans_y);    return 0;}
原创粉丝点击