【平衡树】NOI 2005 维护数列

  上次学习平衡树就是卡在了这里,现在就以这道题做个小结吧。

 

题目在这里http://www.lydsy.com/JudgeOnline/problem.php?id=1500

 

这是NOI以来出的最果的最直接的数据结构题目了,但这明显不代表他简单,第一次做的时候用了2天,现在写起来也是倍感麻烦。

 

关于这道题的感悟我觉得这个博客说的很好,让我受益很多。

http://www.cppblog.com/MatoNo1/archive/2011/06/21/149121.html

 

为了做这道题看了很多文章,看到了郭家宝的文章,让我发现了,“原来郭家宝的splay也是用6个if语句写的”!!!!!

竟然写了245行……虽然我的代码也有230行,但是我喜欢换行、如果调整好格式的话应该是在200以内的。

NOI 2005 维护数列
/**
*Prob    : NOI2005 -- sequence
*Data    : 2012-6-25
*Sol    : Splay
*Author : ZhouHang
*/

#include <cstdio>
#include <cstring>

#define oo 1000000000
#define MaxN 500200

using namespace std;

struct node {
    int v,c[2],p,sz,sum,lmax,rmax,midmax,sm;
    bool rev,d;
} T[MaxN+1];
int root,len,res;
int open,closd;
int a[MaxN],Q[MaxN];

int max(int x,int y) {
    return  x>y?x:y; 
}
int max(int x,int y,int z) {
    int tmp=x>y?x:y;
    if (z>tmp) tmp=z; return tmp;
}
void sc(int _p,int _x,bool _d)
{
    T[_p].c[_d] = _x; T[_x].p = _p; T[_x].d=_d;
}
//新建结点
void newnode(int n,int _v)
{
    T[n].v = T[n].sum = T[n].lmax = T[n].rmax = T[n].midmax = _v;
    T[n].c[0] = T[n].c[1] = 0; T[n].sz = 1; T[n].sm = -oo; T[n].rev=0;
}
//Make_same生效
void sm_opr(int x,int SM)
{
    T[x].sum = T[x].sz * SM;
    if (SM>0) T[x].lmax=T[x].rmax=T[x].midmax=T[x].sum;
    else T[x].lmax=T[x].rmax=T[x].midmax=SM;
}
//旋转生效
void rev_opr(int x)
{
    int c0=T[x].c[0], c1=T[x].c[1];
    sc(x,c0,1); sc(x,c1,0);
    int tmp = T[x].lmax; T[x].lmax = T[x].rmax; T[x].rmax = tmp;
}
//回收到内存池
void era(int x)
{
    if (!x) return;
    if (open==MaxN) open=1; else open++;
    Q[open]=x;
    era(T[x].c[0]); era(T[x].c[1]);
}
//传递标识(音'质')
void dm(int x)
{
    int SM0=T[x].sm;
    if (SM0 != -oo) {
        T[x].v = T[T[x].c[0]].sm = T[T[x].c[1]].sm = SM0; T[x].sm = -oo;
        sm_opr(T[x].c[0],SM0); sm_opr(T[x].c[1],SM0);
    }
    if (T[x].rev) {
        T[T[x].c[0]].rev=!T[T[x].c[0]].rev; T[T[x].c[1]].rev=!T[T[x].c[1]].rev; 
        T[x].rev=0;
        rev_opr(T[x].c[0]); rev_opr(T[x].c[1]);
    }
}
void upd(int x)
{
    int c0=T[x].c[0], c1=T[x].c[1];
    T[x].sz = T[c0].sz + T[c1].sz + 1;
    T[x].sum = T[c0].sum + T[c1].sum + T[x].v;
    T[x].lmax = max(T[c0].lmax,T[c0].sum+T[x].v+max(0,T[c1].lmax));
    T[x].rmax = max(T[c1].rmax,T[c1].sum+T[x].v+max(0,T[c0].rmax));
    T[x].midmax = max(T[c0].midmax, T[c1].midmax, max(T[c0].rmax,0)+T[x].v+max(T[c1].lmax,0));
}
void rot(int x)
{
    int y=T[x].p; bool d=T[x].d;
    if (y==root) { root=x; T[root].p=0; } else sc(T[y].p,x,T[y].d);
    sc(y,T[x].c[!d],d); sc(x,y,!d); upd(y);
}
void splay(int x,int r)
{
    int p0,p;
    while ( (p0=T[x].p)!=r ) {
        p=T[p0].p;
        if (p==r) rot(x);
        else if (T[p0].d==T[x].d) { rot(p0); rot(x); }
             else { rot(x); rot(x); }
    }
    upd(x);
}
int Find_Kth(int K)
{
    int i=root,S0;
    while (i) {
        dm(i);
        S0 = T[T[i].c[0]].sz+1;
        if (K==S0) break;
        else if (K<S0) i=T[i].c[0];
             else { K-=S0; i=T[i].c[1]; }
    }
    return i;
}
//MaKe a new Tree
int mkt(int l,int r)
{
    if (l>r) return 0;
    int n0=Q[closd],mid=(l+r)/2;
    if (closd==MaxN) closd=1; else closd++;
    newnode(n0,a[mid]); 
    int ll=mkt(l,mid-1);
    int rr=mkt(mid+1,r);
    sc(n0,ll,0); sc(n0,rr,1); 
    upd(n0);
    return n0;
}
//各种操作
void ins(int pos)
{
    int p0=Find_Kth(pos); splay(p0,0);
    int p1=Find_Kth(pos+1); splay(p1,root);
    sc(p1,mkt(1,len),0);
    upd(p1); upd(p0);
}
void del(int l,int r)
{
    int p0=Find_Kth(l-1); splay(p0,0);
    int p1=Find_Kth(r+1); splay(p1,root);
    int tmp=T[p1].c[0];
    sc(p1,0,0); upd(p1); upd(p0);
    era(tmp);
}
void mksame(int l,int r,int x)
{
    int p0 = Find_Kth(l-1); splay(p0,0);
    int p1 = Find_Kth(r+1); splay(p1,root);
    int n = T[p1].c[0]; T[n].sm = x; sm_opr(n,x);
    upd(p1); upd(p0);
}
void reve(int l,int r)
{
    int p0 = Find_Kth(l-1); splay(p0,0);
    int p1 = Find_Kth(r+1); splay(p1,root);
    int n = T[p1].c[0]; T[n].rev = !T[n].rev; rev_opr(n);
    upd(p1); upd(p0);
}
int get_sum(int l, int r)
{
    int p0 = Find_Kth(l - 1); splay(p0, 0);
    int p1 = Find_Kth(r + 1); splay(p1, root); 
    int n = T[p1].c[0]; return T[n].sum;
}

int max_sum()
{
    return T[root].midmax;
}

//初始化
void prepare()
{
    T[0].sz = T[0].sum = T[0].lmax = T[0].rmax = T[0].midmax =0;
    for (int i=1; i<=MaxN; i++) Q[i]=i;
    open = MaxN; closd = 3;
    newnode(1,-oo); newnode(2,-oo); sc(1,2,1);
    root = 1; T[root].p = 0;
}

int main()
{
    freopen("sequence.in","r",stdin);
    freopen("sequence.out","w",stdout);

    prepare();
    
    int m,l,r,x;
    scanf("%d%d",&len,&m);
    for (int i=1; i<=len; i++)
        scanf("%d",&a[i]);
    //a数组全部插入树中
    ins(1);
    
    char str[100];
    //scanf("%*c");
    for (int i=1; i<=m; i++)
    {
        scanf("%s",str);
        if (!strcmp(str, "INSERT")) {
            scanf("%d%d",&l,&len);
            for (int j=1; j<=len; j++) 
                scanf("%d",&a[j]);
            ins(++l);
        }
        if (!strcmp(str, "DELETE")) {
            scanf("%d%d",&l,&r);
            r += l++; del(l, r);
        }
        if (!strcmp(str, "MAKE-SAME")) {
            scanf("%d%d%d",&l,&r,&x);
            r += l++; mksame(l, r, x);
        }
        if (!strcmp(str, "REVERSE")) {
            scanf("%d%d", &l, &r);
            r += l++; reve(l, r);
        }
        if (!strcmp(str, "GET-SUM")) {
            scanf("%d%d", &l, &r);
            r += l++; 
            printf("%d\n", get_sum(l, r));
        }
        if (!strcmp(str, "MAX-SUM")) printf("%d\n",max_sum());
        scanf("%*c");
    }
    
    fclose(stdin); fclose(stdout);
    return 0;    
}

 

 

posted @ 2012-06-25 15:00  守護N1身边  阅读(261)  评论(0编辑  收藏  举报