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 <cstdio>

#include <algorithm>

#include <cstring>

#include <string>

#include <queue>

 

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) (r<s(L(t)))

 

queue<int>Q;

 

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++<n;)getint(a[i]);

    build(0,n+1,roof);

    while (m--) {

        string c;

       getstring(c);

        if (c[0]=='I') {

            int x,y,Rs=0;

           getint(x),getint(y);

            for (int i=0;i++<y;)getint(a[i]);

            build(1,y,Rs);

           splay(x,roof,false);

            splay(0,R(roof),false);

           L(R(roof))=Rs;

           update(R(roof));

           update(roof);

        } else {

            if (c[0]=='D') {

                int x,y;

               getint(x),getint(y);

               splay(x-1,roof,false);

               splay(y,R(roof),false);

               Delete(L(R(roof)));

               L(R(roof))=0;

               update(R(roof));

               update(roof);

            } else {

                if (c[0]=='M') {

                    if (c[2]=='K') {

                       int x,y,z;

                       getint(x),getint(y),getint(z);

                       splay(x-1,roof,false);

                       splay(y,R(roof),false);

                       SC(L(R(roof)))=z;

                       update(R(roof));

                       update(roof);

                   } else {

                       splay(0,roof,false);

                       splay(s(roof)-2,R(roof),false);

                       putint(MS(L(R(roof))));

                   }

                } else if (c[0]=='R') {

                    int x,y;

                   getint(x),getint(y);

                   splay(x-1,roof,false);

                    splay(y,R(roof),false);

                   SR(L(R(roof)))^=true;

                   update(R(roof));

                   update(roof);

                } else {

                    int x,y;

                   getint(x),getint(y);

                   splay(x-1,roof,false);

                   splay(y,R(roof),false);

                   putint(S(L(R(roof))));

                }

            }

        }

    }

    return 0;

}


©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,588评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,456评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,146评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,387评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,481评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,510评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,522评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,296评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,745评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,039评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,202评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,901评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,538评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,165评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,415评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,081评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,085评论 2 352

推荐阅读更多精彩内容

  • "use strict";function _classCallCheck(e,t){if(!(e instanc...
    久些阅读 2,028评论 0 2
  • 愿你珍惜。
    浮生未歇ww阅读 248评论 0 0
  • 1、今天新入园,早上起床说要早点去上幼儿园,第一个到了幼儿园,开心的和妈妈说拜拜(出乎我的意料)。中午老师反馈,就...
    毛毛线球阅读 176评论 0 0
  • 亲爱的宝贝女儿: 这是妈妈第一次给你写信,心里有点激动,妈妈有说不完的话想对你说。妈妈想对你说:感谢你来到世...
    judy杨阅读 322评论 0 0
  • 一、关于本书 看过路遥写的《平凡的世界》,作品里没有华丽的文字,朴素的不能再朴素了,但每个细节和动作的描写都很细致...
    3e81098bf2ef阅读 766评论 0 1