BZOJ 3435: [Wc2014]紫荆花之恋

二次联通门 : BZOJ 3435: [Wc2014]紫荆花之恋

二次联通门 : luogu P3920 [WC2014]紫荆花之恋

/*
    luogu P3920 [WC2014]紫荆花之恋

    怀疑人生
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <ctime>
#include <algorithm>
#define rg register
#define INF 1e9
#define EPS 0.78
#define Max 100050
typedef long long LL;
int c[Max * 2][3], h[Max], d[Max], r[Max], li[Max], N, M, EC = 1;
LL Answer; int dis[Max][30], fi[Max], Dis[Max], Zero; bool Flag;
const int BUF = 123123123; char Buf[BUF], *buf = Buf;
inline void read (int &n)
{
     rg char c = getchar ();
     for (n = 0; !isdigit (*buf); ++ buf);
     for (; isdigit (*buf); n = n * 10 + *buf - ‘0‘, ++ buf);
}
inline void Line (int x, int y, int z)
{
    c[++ EC][0] = y, c[EC][1] = fi[x], fi[x] = EC, c[EC][2] = z;
    c[++ EC][0] = x, c[EC][1] = fi[y], fi[y] = EC, c[EC][2] = z;
}
struct Node { Node *c[2]; int v, s, val; };
Node pool[Max * 40], *unp[Max * 40], *Ta = pool, **top = unp, *_r[Max][2], Null, *null = &Null;
struct Balance_Tree
{
    inline Node* Get(int x)
    {
        Node *k = (top != unp) ? *--top : Ta ++;
        k->c[0] = k->c[1] = null, k->s = 1, k->v = x, k->val = rand (); return k;
    }
    inline void Update (Node *x) { x->s = x->c[0]->s + x->c[1]->s + 1; }
    Node *Rebuild (int x, int y)
    {
        Node* R = Get (dis[li[1]][y] - r[li[1]]);
        for (rg int i = 2; i <= x; ++ i)
            Inse_r (R, Get (dis[li[i]][y] - r[li[i]]));
        return R;
    }
    void Rotate (Node *&x, Node *y)
    {
        bool k = y == x->c[0];
        x->c[!k] = y->c[k], y->c[k] = x, y->s=x->s;
        Update(x), x = y; return;
    }
    int Query (Node *x, int y)
    {
        if (x == null) return 0;
        if (y >= x->v) return x->c[0]->s + 1 + Query (x->c[1], y);
        return Query (x->c[0], y);
    }
    void Clear(Node* &x)
    {
        if (x == null) return;
        *top ++ = x, Clear (x->c[0]), Clear (x->c[1]), x = null;
    }
    void Inse_r (Node *&x, Node *y)
    {
        bool flag = y->v > x->v;
        if (x == null) { x = y; return; } else ++ x->s;
        Inse_r (x->c[flag], y);
        if (x->c[flag]->val > x->val) Rotate (x, x->c[flag]);
    }
} B;
#undef Max
struct Divide_Tree
{
#define Max 100050
    int suf[Max], ct[Max], sg[Max], s[Max], R, Sg;
    int Get_R (int C)
    {
        int _C = li[1]; rg int i, j;
        for (i = C; i >= 1; -- i)
            for (s[li[i]] = 1, j = fi[li[i]]; j; j = c[j][1])
                if (!sg[c[j][0]] && s[c[j][0]] > 0) s[li[i]] += s[c[j][0]];
        for (; true; )
        {
            bool flag = false;
            for (i = fi[_C]; i; i = c[i][1])
                if (s[c[i][0]] < s[_C] && !sg[c[i][0]] && s[c[i][0]] * 2 >= C)
                { _C = c[i][0], flag = true; break; }
            if (!flag) break;
        }
        for (i = 1; i <= C; ++ i) s[li[i]] = 0;
        return _C;
    }
    int Get_s (int x)
    {
        int le = 1, ri = 1; li[1] = x, s[x] = -1;
        for (rg int i; le <= ri; ++ le)
            for (i = fi[li[le]]; i; i = c[i][1])
                if (!s[c[i][0]] && !sg[c[i][0]]) s[li[++ ri] = c[i][0]] = -1;
        return ri;
    }
    void Clear (int x)
    {
        if (!sg[x] || sg[x] < Sg) return;
        sg[x] = 0, B.Clear (_r[x][0]), B.Clear (_r[x][1]);
        for (rg int i = fi[x]; i; i = c[i][1]) Clear (c[i][0]);
    }
    void Get (int x, int y)
    {
        ct[x] = 1, sg[x] = sg[suf[x]] + 1; rg int i, j;
        int _f = 0; _r[x][0] = B.Get (-y), _r[x][1] = B.Get (c[EC][2] - y);
        memcpy (dis[x], dis[suf[x]], sizeof dis[suf[x]]);
        for (i = 1; i < sg[x]; ++ i) dis[x][i] += c[EC][2];
        for (dis[x][sg[x]] = 0, i = suf[x], j = sg[x] - 1; i; i = suf[i], -- j)
        {
            ++ ct[i];
            if (j - 1 && ct[i] / (ct[suf[i]] + 1.0) > EPS) _f = suf[i];
            Answer += B.Query (_r[i][0], y - dis[x][j]), B.Inse_r (_r[i][0], B.Get (dis[x][j] - y));
            if (j - 1) Answer -= B.Query (_r[i][1], y - dis[x][j - 1]), B.Inse_r (_r[i][1], B.Get (dis[x][j - 1] - y));
        }
        if (_f) Sg = sg[_f], Clear (_f), Rebuild (_f, Sg, suf[_f]);
    }
    void Rebuild (int x, int y, int z)
    {
        int C = Get_s (x), _C = Get_R (C);
        dis[_C][y] = 0, Dfs (_C, 0, y), sg[_C] = y;
        if (z) suf[_C] = z; else suf[R = _C] = 0, _r[_C][1] = null;
        _r[_C][0] = B.Rebuild (C, y), ct[_C] = C;
        if (y > 1) _r[_C][1] = B.Rebuild (C, y - 1);
        for (rg int i = fi[_C]; i; i = c[i][1])
            if (!sg[c[i][0]]) Rebuild (c[i][0], y + 1, _C);
    }
    void Dfs (int x,int y,int z)
    {
        for (rg int i = fi[x]; i; i = c[i][1])
            if (!sg[c[i][0]] && c[i][0] != y)
                dis[c[i][0]][z] = dis[x][z] + c[i][2], Dfs (c[i][0], x, z);
    }
#undef Max
} A;
int main (int argc, char *argv[])
{
    fread (buf, 1, BUF, stdin);
       read (Zero), read (N), read (Zero), read (Zero), A.R = 1;
    Null.c[0] = Null.c[1] = &Null; int q, w;
    srand (time (0)), read (r[1]),  A.Get (1, r[1]); puts ("0");
    for (rg int i = 2; i <= N; ++ i)
    {
        read (q), q = q ^ (Answer % (int) INF), read (w);
        read (r[i]), h[i] = h[q] + 1, d[i] = d[q] + w;
        Line (i, q, w), A.suf[i] = q, A.Get (i, r[i]);
        printf ("%lld\n", Answer);
    }
    return 0;
}
时间: 2024-11-10 07:29:17

BZOJ 3435: [Wc2014]紫荆花之恋的相关文章

bzoj 3435: [Wc2014]紫荆花之恋 替罪羊树维护点分治 &amp;&amp; AC400

3435: [Wc2014]紫荆花之恋 Time Limit: 240 Sec  Memory Limit: 512 MBSubmit: 159  Solved: 40[Submit][Status][Discuss] Description 强 强和萌萌是一对好朋友.有一天他们在外面闲逛,突然看到前方有一棵紫荆树.这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从紫荆树上长了出来. 仔细看看的话,这个大树实际上是一个带权树.每个时刻它会长出一个新的叶子节点.每个节点上有一个可爱的小精灵,

BZOJ 3435 Wc2014 紫荆花之恋 动态树分治+替罪羊树+Treap

题目大意:给定一棵树,每次添加一个节点并询问当前有多少点对满足dis(i,j)<=ri+rj 强制在线 吾辈有生之年终于把这道题切了...QAQ 什么?你想做这题? 1095切了么?没?去把1095切掉再说! 3065切了么?没?去把3065切掉再说! 什么?都切了?那还不会做这题?? -- 算了还是说说做法吧... 我们抛开那些乱七八糟的,考虑朴素做法 首先式子的形式是dis(i,j)<=ri+rj,令p=lca(i,j),把式子变形可以得到dis(j,p)-rj<=ri-dis(i,

Wc2014 紫荆花之恋

哈哈哈哈哈哈哈哈哈哈哈哈我终于过了!!!!!!!!!!!!!!! 从昨天上午就开始写了,下午回家之后调了一会儿没什么感觉,就删了重打了一遍,然后调了一晚上+今天半个上午......我*******终于过了...... 我是萌萌的传送门 我是另一个萌萌的传送门 一道极其恶心的动态树分治...... 首先点分治,限制条件就变成了di+dj<=ri+rj,移项得rj-dj>=di-ri,对重心和子树开平衡树维护di-ri即可. 查询的时候先跳点分治树更新答案,然后逐层把di-ri插入平衡树,上跳的过

【BZOJ3435】[Wc2014]紫荆花之恋 替罪点分树+SBT

[BZOJ3435][Wc2014]紫荆花之恋 Description 强强和萌萌是一对好朋友.有一天他们在外面闲逛,突然看到前方有一棵紫荆树.这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从紫荆树上长了出来.仔细看看的话,这个大树实际上是一个带权树.每个时刻它会长出一个新的叶子节点.每个节点上有一个可爱的小精灵,新长出的节点上也会同时出现一个新的小精灵.小精灵是很萌但是也很脆弱的生物,每个小精灵 i 都有一个感受能力值Ri ,小精灵 i, j 成为朋友当且仅当在树上 i 和 j 的距离

【bzoj3435】[Wc2014]紫荆花之恋 替罪点分树套SBT

题目描述 强强和萌萌是一对好朋友.有一天他们在外面闲逛,突然看到前方有一棵紫荆树.这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从紫荆树上长了出来.仔细看看的话,这个大树实际上是一个带权树.每个时刻它会长出一个新的叶子节点.每个节点上有一个可爱的小精灵,新长出的节点上也会同时出现一个新的小精灵.小精灵是很萌但是也很脆弱的生物,每个小精灵 i 都有一个感受能力值Ri ,小精灵 i, j 成为朋友当且仅当在树上 i 和 j 的距离 dist(i,j) ≤ Ri + R! ,其中 dist(i

UOJ#55 [WC2014]紫荆花之恋

题目描述 强强和萌萌是一对好朋友.有一天他们在外面闲逛,突然看到前方有一棵紫荆树.这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从紫荆树上长了出来. 仔细看看的话,这个大树实际上是一个带权树.每个时刻它会长出一个新的叶子节点,每个节点上有一个可爱的小精灵,新长出的节点上也会同时出现一个新的小精灵.小精灵是很萌但是也很脆弱的生物,每个小精灵 \(i\) 都有一个感受能力值 \(r_i\),小精灵 \(i, j\) 成为朋友当且仅当在树上 \(i\) 和 \(j\) 的距离 \(\text{

P3920 [WC2014]紫荆花之恋 [点分树,替罪羊树]

点分树搞出来,然后搞个快点的平衡树. 点分树膨胀的时候就搞重构,没了...说的这么轻巧倒是写了3h 23333 // powered by c++11 // by Isaunoya #include <bits/stdc++.h> #define rep(i, x, y) for (register int i = (x); i <= (y); ++i) #define Rep(i, x, y) for (register int i = (x); i >= (y); --i) #

#55. 【WC2014】紫荆花之恋

强强和萌萌是一对好朋友.有一天他们在外面闲逛,突然看到前方有一棵紫荆树.这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从紫荆树上长了出来. 仔细看看的话,这个大树实际上是一个带权树.每个时刻它会长出一个新的叶子节点,每个节点上有一个可爱的小精灵,新长出的节点上也会同时出现一个新的小精灵.小精灵是很萌但是也很脆弱的生物,每个小精灵 ii 都有一个感受能力值 riri,小精灵 i,ji,j 成为朋友当且仅当在树上 ii 和 jj 的距离 dist(i,j)≤ri+rjdist(i,j)≤ri

数据结构(平衡树,树分治,暴力重构):WC 2014 紫荆花之恋

[题目描述] 强强和萌萌是一对好朋友.有一天他们在外面闲逛,突然看到前方有一棵紫荆树.这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从紫荆树上长了出来. 仔细看看的话,这棵大树实际上是一个带权树.每个时刻他会长出一个新的叶子节点.每个节点上有一个可爱的小精灵,新长出的节点上也会同时出现一个新的小精 灵.小精灵是很萌但是也很脆弱的生物,每个小精灵i都有一个感受能力ri,小精灵i,j成为朋友当且仅当在树上i和j的距离 dist(i,j)<=ri+rj,其中dist(i,j)表示在这棵树上i和