cyand1317

分类

链接

RSS

RSS Link
[BZOJ 2157] 旅游
[HDU 1532] [POJ 1273] Drainage Ditches

[BZOJ 2049] [Luogu P2147] [SDOI 2008] Cave 洞穴勘测

cyand1317 posted @ 2016年4月03日 17:13 in 未分类 with tags Splay LCT BZOJ Luogu , 643 阅读

第一次……调完……LCT……上来……水一发…… _(:_」∠)_

样例数据一点也不良心的 LCT 模版题……

周四听了一节课之后啃论文。。感觉 Link/cut tree 并不难的样子 = = 于是昨天晚上下定决心开始码 LCT!(۶* ‘ヮ’)۶”

 

首先。。决定再手写一遍 Splay。。“应该不会出错的” ← flag *1

然后。。换了一种方法写 Splay 旋转操作。。“好像和原来是一样的” ← flag *2

然后 bla bla bla,bla bla bla。。。。。

码完一堆 Syntax error。。改掉之后直接输入样例各种崩溃。。。好不容易正常了。。自己构造数据狂 RE/WA 不止。。。

(凌晨1点)什么鬼啊不玩了不玩了 (╯°□°)╯︵ ┻━┻(哔——)

然后就梦见写 LCT 了 = = 果然是应了 BZOJ 上的 Nickname 么(笑)[ゆめで すぐ あえるね おやすみなさい]


坐在英语课堂上憋了一上午 = =

(下午2点)不想重写。。继续开始调。。不信今天调不出来 > <

首先用洛谷上的并查集乱搞法 Link/cut disjoint-set(大雾)做一个数据生成器

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAXN 10008

int n, m;
int par[MAXN];
void lcdsu_init()
{
    int i;
    for (i = 0; i < n; ++i) par[i] = -1;
}
int lcdsu_root(int u)
{
    while (par[u] != -1) u = par[u];
    return u;
}
void lcdsu_evert(int u)
{
    int v = par[u], t;
    par[u] = -1;
    while (v != -1) {
        t = par[v];
        par[v] = u;
        u = v; v = t;
    }
}
void lcdsu_union(int u, int v)
{
    lcdsu_evert(u);
    lcdsu_evert(v);
    if (rand() & 1) par[u] = v; else par[v] = u;
}
void lcdsu_cut(int u, int v)
{
    if (par[u] == v) par[u] = -1;
    else par[v] = -1;
}

int main()
{
    unsigned int seed = (unsigned)time(NULL);
    fprintf(stderr, "Seed: %u\n", seed);
    srand(seed);

    scanf("%d%d", &n, &m);
    lcdsu_init();
    printf("%d %d\n", n, m);

    int u, v;
    do {
        u = rand() % n; v = rand() % n;
        if (rand() & 1) {
            if (lcdsu_root(u) == lcdsu_root(v)) {
                if (par[u] == v || par[v] == u) {
                    lcdsu_cut(u, v);
                    printf("Destroy %d %d\n", u + 1, v + 1);
                } else {
                    printf("Query %d %d\n", u + 1, v + 1);
                }
            } else {
                lcdsu_union(u, v);
                printf("Connect %d %d\n", u + 1, v + 1);
            }
        } else {
            printf("Query %d %d\n", u + 1, v + 1);
        }
    } while (--m);

    return 0;
}

然后发现好像顺便把题目也做了 ( ゚д゚) 随便改几行交上去然后发现过了。。。然后交到 BZOJ 上也顺利通过了(−_−;)

/**************************************************************
    Problem: 2049
    User: cyand1317
    Language: C
    Result: Accepted
    Time:808 ms
    Memory:792 kb
****************************************************************/
 
#include <stdio.h>
#include <stdlib.h>
#define MAXN 10008
 
int n, m;
int par[MAXN];
void lcdsu_init()
{
    int i;
    for (i = 0; i < n; ++i) par[i] = -1;
}
int lcdsu_root(int u)
{
    while (par[u] != -1) u = par[u];
    return u;
}
void lcdsu_evert(int u)
{
    int v = par[u], t;
    par[u] = -1;
    while (v != -1) {
        t = par[v];
        par[v] = u;
        u = v; v = t;
    }
}
void lcdsu_union(int u, int v)
{
    lcdsu_evert(u);
    lcdsu_evert(v);
    if (rand() & 1) par[u] = v; else par[v] = u;
}
void lcdsu_cut(int u, int v)
{
    if (par[u] == v) par[u] = -1;
    else par[v] = -1;
}
 
int main()
{
    scanf("%d%d", &n, &m);
    lcdsu_init();
 
    char op[16]; int u, v;
    do {
        scanf("%s%d%d", op, &u, &v); --u; --v;
        switch (op[0]) {
            case 'C': lcdsu_union(u, v); break;
            case 'D': lcdsu_cut(u, v); break;
            case 'Q': puts(lcdsu_root(u) == lcdsu_root(v) ? "Yes" : "No"); break;
        }
    } while (--m);
 
    return 0;
}

好吧。。

不过还是得滚回去写 LCT。。。

Crash 调调调。。调调调。。。终于不 crash 啦!随机一组大数据继续炸。。。

继续调调调。。调调调。。。终于不 crash 啦!另外随机一组大数据继续炸。。。

好像 Splay 写错了 = = 啊不对没有 = = 啊不对好像真的写错了 = =

……

……

最后发现-_-# Splay 旋转的时候没有 push -_-# 导致有时候要断开和右子树的连接,但有时因为延迟反转标记没推下去而切下的实际是左子树。。。

什么鬼啊这也行 ◡ ヽ(`Д´)ノ ┻━┻  智障了大半天才发现啊。。。

改掉。。对拍。。好像对了?(怀疑电脑 ing)

随机 max 数据。。。再随机一组。。再随机一组。。。。。。擦 真的对了真的对了!!!!

好激动~~~~!!!!!!

/**************************************************************
    Problem: 2049
    User: cyand1317
    Language: C++
    Result: Accepted
    Time:3920 ms
    Memory:1060 kb
****************************************************************/
 
#include <cstdio>
#include <cstdlib>
static const int MAXN = 10007;
inline void swap(int &a, int &b) { static int t; t = a; a = b; b = t; }
 
struct __spl_node {
    int child[2], parent;
    bool lz_rev;
} t[MAXN];
 
int spl_epoch = 0;
int ppar[MAXN];
inline int spl_newnode(int parent = -1)
{
    int idx = spl_epoch++;
    t[idx].child[0] = t[idx].child[1] = -1;
    t[idx].parent = parent;
    t[idx].lz_rev = false;
    return idx;
}
inline void spl_push(int idx)
{
    if (idx != -1 && t[idx].lz_rev) {
        t[idx].lz_rev = false;
        if (t[idx].child[0] != -1) t[t[idx].child[0]].lz_rev ^= 1;
        if (t[idx].child[1] != -1) t[t[idx].child[1]].lz_rev ^= 1;
        swap(t[idx].child[0], t[idx].child[1]);
    }
    if (idx != -1) {
        if (t[idx].child[0] != -1) ppar[t[idx].child[0]] = ppar[idx];
        if (t[idx].child[1] != -1) ppar[t[idx].child[1]] = ppar[idx];
    }
}
inline void spl_rotate(int i, int d)
{
    int p = t[i].parent, g = t[p].parent;
    t[p].child[d] = t[i].child[1 - d];
    t[t[i].child[1 - d]].parent = p;
    t[i].child[1 - d] = p;
    t[p].parent = i;
    if (g != -1) t[g].child[t[g].child[1] == p] = i;
    t[i].parent = g;
}
inline void spl_zig(int idx) { spl_rotate(idx, 0); }
inline void spl_zag(int idx) { spl_rotate(idx, 1); }
inline void spl_1splay(int idx)
{
    spl_push(idx);
    spl_rotate(idx, t[t[idx].parent].child[1] == idx);
}
inline void spl_2splay(int idx, int under)
{
    int par = t[idx].parent, gpn = t[par].parent;
    spl_push(idx);
    if (gpn == under) spl_1splay(idx);
    else {
        if (t[gpn].child[0] == par) {
            if (t[par].child[0] == idx) { spl_zig(par); spl_zig(idx); }
            else                        { spl_zag(idx); spl_zig(idx); }
        } else {
            if (t[par].child[0] == idx) { spl_zig(idx); spl_zag(idx); }
            else                        { spl_zag(par); spl_zag(idx); }
        }
    }
}
inline void spl_lift(int idx, int under = -1)
{
    static int chain[MAXN];
    int top = 0, u = idx;
    while (u != under) chain[top++] = (u = t[u].parent);
    for (; top >= 0; --top) spl_push(chain[top]);
    while (t[idx].parent != under) spl_2splay(idx, under);
}
inline void spl_cut(int idx, int child_id)
{
    int cld = t[idx].child[child_id];
    if (cld != -1) {
        t[idx].child[child_id] = -1;
        t[cld].parent = -1;
    }
}
inline void spl_link(int idx, int child_id, int cld)
{
    //assert(t[cld].parent == -1);
    //assert(t[idx].child[child_id] == -1);
    t[cld].parent = idx;
    t[idx].child[child_id] = cld;
}
inline int spl_leftmost(int idx, int lift_under = -1)
{
    int cld = idx;
    while (t[cld].child[0] != -1) cld = t[cld].child[0];
    spl_lift(cld, lift_under);
    return cld;
}
 
inline void lct_init(int n)
{
    for (int i = 1; i <= n; ++i) ppar[i] = -1;
}
void lct_access(int u)
{
    spl_lift(u); spl_push(u);
    if (t[u].child[1] != -1) ppar[t[u].child[1]] = u; spl_cut(u, 1);
    u = spl_leftmost(u);
    int v;
    //assert(t[u].parent == -1);
    while ((v = ppar[u]) != -1) {
        spl_lift(v); spl_push(v);
        if (t[v].child[1] != -1) ppar[t[v].child[1]] = v; spl_cut(v, 1);
        //assert(t[u].parent == -1);
        spl_link(v, 1, u);
        u = spl_leftmost(v);
    }
}
void lct_evert(int u)
{
    lct_access(u);
    spl_lift(u);
    t[u].lz_rev ^= 1;
    ppar[u] = -1;
}
int lct_getroot(int u)
{
    int v = u;
    do {
        u = v;
        lct_access(u);
        spl_lift(u);
        u = spl_leftmost(u);
    } while ((v = ppar[u]) != -1);
    return spl_leftmost(u);
}
void lct_link(int u, int v) // u.father := v
{
    lct_evert(u);
    ppar[u] = v;
    lct_access(u);
}
void lct_cut(int u, int v)
{
    lct_evert(u);
    spl_lift(v);
    lct_access(v);
    spl_lift(u);
    spl_push(u);
    if (t[u].child[1] != -1) ppar[t[u].child[1]] = -1; spl_cut(u, 1);
}
 
int n, m;
 
int main()
{
    scanf("%d%d", &n, &m);
    spl_newnode(-1);
    for (int i = 0; i < n; ++i) spl_newnode(-1); //assert(spl_newnode(i + 1) == i + 1);
    lct_init(n);
 
    char op[16];
    int u, v;
    do {
        scanf("%s%d%d", op, &u, &v);
        switch (op[0]) {
            case 'Q': puts(lct_getroot(u) == lct_getroot(v) ? "Yes" : "No"); break;
            case 'C': lct_link(u, v); break;
            case 'D': lct_cut(u, v); break;
            default: break;
        }
    } while (--m);
 
    return 0;
}

(像窝这样代码长度上天的。。居然只写了 5 KB 不到。。手动鼓掌)(然而如此之乱)

感觉洛谷好像被卡出 bug 了。。。奥妙重重

(is-programmer 似乎发抽了。。屏幕截图:“通过该测试点”×10 以及 “Unaccepted,40 分”) 在这里围观 bug~

 

好吧总算是又填平了一个大坑 (๑˃̵ᴗ˂̵)و

今天是切不动题了 (/_ ;) 窝需要静静


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter