您的位置:首页 > 其它

BZOJ 1251 绳命中第一道SPLAY

2015-12-25 16:23 169 查看
不要问蒟蒻标题是怎么回事。蒟蒻就是蒟蒻,T^T到现在才会写SPLAY。

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

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

find()过程中要pushdown

rotate()前要分别pushdown父节点和当前节点,之后要分别maintain父节点和当前节点

rotate()过程中别忘了P[fa].fa的一个字节点指针要改变

合并和分裂操作过程中也要pushdown和maintain

注意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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: