BZOJ-1500: [NOI2005]维修数列 题解(Splay 维护序列 )

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

第一次遇到这么恶心的数据结构,最开始的时候建树没有平衡建树,结果各种TLE,最大的点跑到了10s,左右,用了堆式建树速度一下子就剩下1s以内了。(建树方法:每次取出序列中中间的数建立节点,然后序列左边部分作为其左子树,右边作为其右子树,然后递归建树)(BZOJ的内存卡的挺紧的,所以要用个队列之类的回收数组节点,然后再次利用(目测在BZOJ开了O2的情况下,直接用指针的delete(),new()速度也相差无几))

操作的实现方法(splay(r,t)表示将子树t中的第r个数旋转到t所在位置,第r个数即select(r,t),s(t)表示子树大小):

splay节点维护的信息:LS(从左起的最大连续和),RS(从右起的最大连续和),S(区间和),MS(最大连续和),SR(翻转标记),SC(修改标记),V(节点权值),s(子树大小)

其中LS,RS,MS,S,V都是维护操作六必须的。

维护MS,LS,RS的递推式:

LS(t)=max(max(LS(L(t)),S(L(t))+V(t)),S(L(t))+V(t)+LS(R(t)))

RS(t)=max(max(RS(R(t)),S(R(t))+V(t)),S(R(t))+V(t)+RS(L(t)))

MS(t)=max(max(MS(L(t)),MS(R(t))),max(max(RS(L(t))+V(t),LS(R(t))+V(t)),max(V(t),RS(L(t))+LS(R(t))+V(t))))

INSERT:splay(pos,roof) splay(0,R(roof)) 然后平衡建树,把该树的根连到roof右子树的左子树上

DELETE:splay(pos-1,roof) splay(tot,R(roof)) 然后对子树L(R(roof))回收节点,再置空

MAKE-SAME:splay(pos-1,roof) splay(tot,R(roof)) 然后对子树L(R(roof))打标记

REVERSE:方法与MAKE-SAME一样

GET-SUM:splay(pos-1,roof) splay(tot,R(roof)) 然后输出子树L(R(roof))维护的序列和信息

MAX-SUM:splay(0,roof) splay(s(roof)-2,R(roof)) 然后输出子树L(R(roof))维护的最大连续和信息

代码(效率依旧平平):

#include 

#include 

#include 

#include 

#include 

 

using namespace std;

 

#define inf (1<<19)

#define MAXN 500010

#define L(t) Left[t]

#define R(t) Right[t]

#define s(t) Size[t]

#define V(t) Value[t]

#define SR(t) Sign_Reverse[t]

#define SC(t) Sign_Change[t]

#define S(t) Sum[t]

#define LS(t) Left_Sum[t]

#define RS(t) Right_Sum[t]

#define MS(t) Max_Sum[t]

#define C(r,t) (rQ;

 

int Left[MAXN],Right[MAXN],Size[MAXN],Value[MAXN],Sum[MAXN];

bool Sign_Reverse[MAXN];

int Sign_Change[MAXN],Left_Sum[MAXN],Right_Sum[MAXN],Max_Sum[MAXN];

int n,m,a[MAXN],M=0,roof,Troof=0;

 

void getstring(string &c) {

    c="";

    int ch;

    for (ch=getchar();ch==' '||ch=='\n';ch=getchar()) ;

    c+=char(ch);

    for (ch=getchar();ch!=' '&&ch!='\n';ch=getchar()) c+=char(ch);

}

 

void getint(int &t) {

    int ch;

    bool flag=false;

    for (ch=getchar();!(ch>=int('0')&&ch<=int('9'));ch=getchar()) if (ch==int('-')) flag=true;

    t=ch-int('0');

    for (ch=getchar();ch>=int('0')&&ch<=int('9');ch=getchar()) t*=10,t+=ch-int('0');

    t=flag?(-t):t;

}

 

void putint(int t) {

    if (!t) { putchar(int('0')); putchar(int('\n')); return ; }

    int ch[20];

    ch[0]=0;

    if (t<0) putchar(int('-')),t=-t;

    while (t) {

        ch[++ch[0]]=t%10;

        t/=10;

    }

    for (int i=ch[0];i;i--) putchar(int('0')+ch[i]);

    putchar(int('\n'));

}

 

void Init(int t) {

   L(t)=R(t)=V(t)=S(t)=s(t)=0;

   LS(t)=RS(t)=MS(t)=-inf;

    SR(t)=false,SC(t)=-inf;

}

 

void pushdown(int t) {

    if (t) {

        if (SR(t)) {

           swap(LS(t),RS(t)),swap(L(t),R(t));

           SR(L(t))^=true,SR(R(t))^=true,SR(t)^=true;

        }

        if (SC(t)!=-inf) {

           V(t)=SC(t);

           S(t)=s(t)*SC(t);

            LS(t)=RS(t)=MS(t)=max(S(t),V(t));

           SC(L(t))=SC(R(t))=SC(t);

           SC(t)=-inf;

        }

    }

}

 

void update(int t) {

    pushdown(t);

   pushdown(L(t)),pushdown(R(t));

   S(t)=S(L(t))+S(R(t))+V(t),s(t)=s(L(t))+s(R(t))+1;

    LS(t)=max(max(LS(L(t)),S(L(t))+V(t)),S(L(t))+V(t)+LS(R(t)));

   RS(t)=max(max(RS(R(t)),S(R(t))+V(t)),S(R(t))+V(t)+RS(L(t)));

   MS(t)=max(max(MS(L(t)),MS(R(t))),max(max(RS(L(t))+V(t),LS(R(t))+V(t)),max(V(t),RS(L(t))+LS(R(t))+V(t))));

}

 

void zag(int &t) {

    pushdown(t);

    pushdown(R(t));

    int k=R(t);

   R(t)=L(k);update(t);

   L(k)=t;t=k;update(t);

}

 

void zig(int &t) {

    pushdown(t);

    pushdown(L(t));

    int k=L(t);

   L(t)=R(k);update(t);

   R(k)=t;t=k;update(t);

}

 

bool splay(int r,int &t,bool flag) {

    pushdown(t);

    if (s(L(t))==r) {

        return false;

    }

    bool w=splay(C(r,t)?r:r-s(L(t))-1,C(r,t)?L(t):R(t),true);

    if (w) {

        if (C(r,t)) {

            if (C(r,L(t))) zig(t); else zag(L(t));

            zig(t);

        } else {

            if (!C(r-s(L(t))-1,R(t))) zag(t) ; else zig(R(t));

            zag(t);

        }

    } else if (!flag) if C(r,t) zig(t) ; else zag(t);

    return w^true;

}

 

int New() {

    if (Q.empty()) return ++M

    ;  else {

        int k=Q.front();

        Q.pop();

        return k;

    }

}

 

void Delete(int t) {

    if (!t) return ;

    Q.push(t);

   Delete(L(t)),Delete(R(t));

}

 

void build(int l,int r,int &t) {

    if (l>r) { t=0; return ; }

    int mid=(l+r)>>1;

    t=New();

    V(t)=a[mid],s(t)=r-l+1;

    SR(t)=false,SC(t)=-inf;

    build(l,mid-1,L(t)),build(mid+1,r,R(t));

    update(t);

}

 

int main() {

    while (!Q.empty()) Q.pop();

   memset(Sign_Reverse,0,sizeof(Sign_Reverse));

    Init(0);

   getint(n),getint(m);

    a[0]=a[n+1]=0;

    for (int i=0;i++

你可能感兴趣的:(BZOJ-1500: [NOI2005]维修数列 题解(Splay 维护序列 ))