BZOJ 1251 绳命中第一道SPLAY

来源:互联网 发布:拍淘宝照片用什么软件 编辑:程序博客网 时间:2024/04/30 09:39

不要问蒟蒻标题是怎么回事。蒟蒻就是蒟蒻,T^T到现在才会写SPLAY。

感觉这道题的SPLAY也没啥好讲的,很基础。第一次写SPLAY,不过思路还是比较明朗。只不过最开始写这道题的时候傻乎乎的只给“加”的操作打标记,没给“翻转”打标记,T了一次。再加上自己这凌乱的代码、数不清的细节错误,调了老长时间。

有这么一些值得我注意的细节:

  1. find()过程中要pushdown
  2. rotate()前要分别pushdown父节点和当前节点,之后要分别maintain父节点和当前节点
  3. rotate()过程中别忘了P[fa].fa的一个字节点指针要改变
  4. 合并和分裂操作过程中也要pushdown和maintain
  5. 注意P[0]的值不要影响有效的节点的值的计算
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;void get (int &x){    char c = getchar(); bool neg = 0; x = 0;    while (c < '0' || c > '9') {if (c == '-') neg = 1; c = getchar();}    while (c <= '9' && c >= '0') x = x*10+c-48, c = getchar();    if (neg) x = -x;}void put (int x){    if (x < 0) {putchar ('-'); x = -x;}    if (x == 0) {putchar ('0');}    char s[15]; int num = 0;    while (x) s[++num] = (x%10)+48, x /= 10;    while (num) putchar (s[num--]);    putchar ('\n');}struct node {    int k, lc, rc, fa, sz, ad, re, mx;    void reset() {k=lc=rc=fa=sz=ad=re=0; mx=-(1<<30);}};struct SplayTree{    node P[50005]; int cnt, root;    void build (int rt, int sz)    {        P[rt].sz = sz; int half = sz>>1;        if (half) {P[++cnt].fa=rt, P[rt].lc=cnt; build(cnt,half);}        half = sz - half - 1;        if (half) {P[++cnt].fa=rt, P[rt].rc=cnt; build(cnt,half);}    }    void initialize (int sz) {build(cnt=root=1, sz);}    void pushdown (int rt)    {        if (P[rt].ad)        {            int ad = P[rt].ad, lc = P[rt].lc, rc = P[rt].rc;            P[lc].k += ad, P[lc].ad += ad, P[lc].mx += ad;            P[rc].k += ad, P[rc].ad += ad, P[rc].mx += ad;            P[rt].ad = 0;        }        if (P[rt].re)        {            int lc = P[rt].lc, rc = P[rt].rc;            swap(P[lc].lc, P[lc].rc);            swap(P[rc].lc, P[rc].rc);            P[lc].re ^= 1, P[rc].re ^= 1;            P[rt].re = 0;        }    }    void maintain (int rt)    {        P[0].reset();        int lc = P[rt].lc, rc = P[rt].rc;        P[rt].sz = P[lc].sz + P[rc].sz + 1;        P[rt].mx = max (max(P[lc].mx,P[rc].mx), P[rt].k);    }    int find (int rt, int k)    {        int rk = P[P[rt].lc].sz+1;        if (rk == k) return rt;        pushdown(rt);        if (rk > k) return find (P[rt].lc, k);        if (rk < k) return find (P[rt].rc, k-rk);    }    void rotate (int rt)    {        int fa = P[rt].fa, gfa = P[fa].fa;        pushdown(fa); pushdown(rt);        if (P[fa].lc == rt)        {            P[fa].lc = P[rt].rc, P[P[rt].rc].fa = fa;            P[rt].rc = fa, P[fa].fa = rt;        }        else        {            P[fa].rc = P[rt].lc, P[P[rt].lc].fa = fa;            P[rt].lc = fa, P[fa].fa = rt;        }        if(P[gfa].lc==fa) P[gfa].lc=rt;         else P[gfa].rc=rt;        P[rt].fa = gfa;        if (fa == root) root = rt, P[rt].fa = 0;        maintain(fa); maintain(rt);    }    void splay (int rt)    {        while(rt!=root)        {            int fa = P[rt].fa, gfa = P[fa].fa;            if(gfa&&(P[fa].lc==rt)==(P[gfa].lc==fa)) rotate(fa);            rotate(rt);        }    }    void merge (int L, int R)    {        if (!L) {root=R; return;}        if (!R) {root=L; return;}        root = L;        splay (find(L,P[L].sz));        pushdown (root);        P[root].rc = R, P[R].fa = root;        maintain (root);    }    int split (int k, bool po)    {        int rt = find (root, k), t;        splay (rt); pushdown (rt);        if (po) t=P[rt].lc, P[rt].lc=0;        else t=P[rt].rc, P[rt].rc=0;        P[t].fa = 0; maintain(rt);        return t;    }    void add (int L, int R, int V)    {        int op = split(L,1), op2 = split(R-L+1,0);        P[root].k+=V, P[root].mx+=V, P[root].ad+=V;        merge (root,op2);        merge (op, root);    }    void rever (int L, int R)    {        int op = split(L,1), op2 = split(R-L+1,0);        swap(P[root].lc, P[root].rc);        P[root].re ^= 1;        merge (root,op2);        merge (op, root);    }    void getmax (int L, int R)    {        int op = split(L,1), op2 = split(R-L+1,0);        put (P[root].mx);        merge (root,op2);        merge (op, root);    }}Solve;int n, m;int main (){    get (n); get (m);    Solve.initialize(n);    while (m--)    {        int cmd, L, R, V; get (cmd); get (L); get (R);        if (cmd == 1) {get (V); Solve.add(L,R,V);}        if (cmd == 2) Solve.rever(L,R);         if (cmd == 3) Solve.getmax(L,R);    }    return 0;}
0 0
原创粉丝点击