BZOJ1500 [NOI2005]维修数列

初看这道题,被吓到了....

思路就不多说了,已经很多人研究过这道题。

参考的博客:

https://www.byvoid.com/blog/noi-2005-sequence/

http://www.cnblogs.com/kuangbin/archive/2013/08/28/3287822.html

<pre name="code" class="cpp">#include<stdio.h>
#include<algorithm>
using namespace std;
const int maxn = 5e5+10;
const int inf = 1e8+1000;
#define Key_val root->c[1]->c[0]
struct Snode
{
    Snode *p,*c[2];
    int key,sz,num,sum,mx,lx,rx;
    bool rev,same;
    bool getlr(){return p->c[1]==this;}
    Snode *link(int w,Snode *x,Snode *null){c[w]=x;if(x!=null)x->p=this;return this;}
}S[maxn],*root,*null,*lb,*rb;
int sa[maxn],tot1,tot2;
int a[maxn];
int n,q;

Snode *NewNode(int key, Snode *p)
{
    int r;
    if(tot2) r = sa[tot2--];
    else r = ++tot1;
    Snode *e = S+r;
    e->p = p;
    e->sz = e->num = 1;
    e->key = e->sum = e->mx = e->lx = e->rx = key;
    e->same = e->rev = false;
    e->c[0] = e->c[1] = null;
    return e;
}

void Updata_same(Snode *x, int v)
{
    if(x == null) return;
    x->same = 1;  x->key = v;
    x->sum = v*x->sz;
    x->lx = x->rx = x->mx = max(v, x->sum);
}

void Updata_rev(Snode *x)
{
    if(x == null) return;
    swap(x->c[0], x->c[1]);
    swap(x->lx, x->rx);
    x->rev ^= 1;
}

void pushdown(Snode *x)
{
    if(x == null) return;
    if(x->same)
    {
        Updata_same(x->c[0], x->key);
        Updata_same(x->c[1], x->key);
        x->same = 0;
    }
    if(x->rev)
    {
        Updata_rev(x->c[0]);
        Updata_rev(x->c[1]);
        x->rev = 0;
    }
}

void pushup(Snode *x)
{
    if(x == null) return;
    Snode *ls = x->c[0], *rs = x->c[1];
    x->sz = ls->sz + rs->sz + x->num;
    x->sum = ls->sum + rs->sum + x->key;
    x->lx = max(ls->lx, ls->sum + x->key + max(0, rs->lx));
    x->rx = max(rs->rx, rs->sum + x->key + max(0, ls->rx));
    x->mx = max(0, ls->rx) + x->key + max(0, rs->lx);
    x->mx = max(x->mx, max(ls->mx, rs->mx));
}

void dfs(Snode *x)
{
    if(x == null) return;
    ///pushdown(x);
    dfs(x->c[0]);
    printf("%d sz:%d sum:%d\n",x->key,x->sz,x->sum);
    dfs(x->c[1]);
}

void test()
{
    dfs(root);
    puts("");
}

Snode* Build(int l,int r,Snode *p)
{
    if(l > r) return null;
    int mid = (l+r)/2;
    Snode *x = NewNode(a[mid], p);
    x->c[0] = Build(l,mid-1,x);
    x->c[1] = Build(mid+1,r,x);
    pushup(x);
    return x;
}

void rot(Snode *x)
{
    Snode *q = x->p->p;
    int o = x->getlr();
    x->link(!o,x->p->link(o,x->c[!o],null),null);
    pushup(x->p);
    if(q!=null) q->link(q->c[1]==x->p, x,null);
    else {x->p=null; root=x;}
}

void splay(Snode *x,Snode *tar)
{
    pushdown(x);///这是要加上的...
    while(x->p!=tar && x->p->p!=tar)
    {
        pushdown(x->p->p);
        pushdown(x->p);
        pushdown(x);
        x->getlr()==x->p->getlr()?rot(x->p):rot(x),rot(x);
    }
    if(x->p!=tar)
    {
        pushdown(x->p);
        pushdown(x);
        rot(x);
    }
    pushup(x);
}
#define lsz x->c[0]->sz
void select(int k, Snode *y)
{
    Snode *x = root;
    pushdown(x);
    while(!(lsz < k && lsz + x->num >= k))
    {
        if(k <= lsz)
            x = x->c[0];
        else
        {
            k -= lsz + x->num;
            x = x->c[1];
        }
        pushdown(x);
    }
    splay(x, y);
}

void Insert(int pos,int tot)
{
    for(int i=0;i<tot;i++) scanf("%d",&a[i]);
    select(pos+1,null);
    select(pos+2,root);
    Key_val=Build(0,tot-1,root->c[1]);
    pushup(root->c[1]);
    pushup(root);
}

void earse(Snode *x)
{
    if(x==null) return;
    sa[++tot2] = x-S;
    earse(x->c[0]);
    earse(x->c[1]);
}

void Delete(int pos,int tot)
{
    select(pos,null);
    select(pos+tot+1,root);
    earse(Key_val);
    Key_val = null;
    splay(root->c[1],null);
}

void Reverse(int pos,int tot)
{
    select(pos,null);
    select(pos+tot+1,root);
    Updata_rev(Key_val);
    splay(Key_val,null);
}

void MakeSame(int pos,int tot,int value)
{
    select(pos,null);
    select(pos+tot+1,root);
    Updata_same(Key_val, value);
    splay(Key_val,null);
}

int GetSum(int pos, int tot)
{
    select(pos, null);
    select(pos+tot+1, root);
    return Key_val->sum;
}

int MaxSum()
{
    return root->mx;
}

void init()
{
    tot1 = tot2 = 0;
    null = NewNode(-inf, 0);
    null->c[0] = null->c[1] = null;
    lb = root = NewNode(-inf, null);
    rb = root->c[1] = NewNode(-inf, root);
    null->sz = 0;
    null->sum = lb->sum = rb->sum = 0;
    pushup(root);
}

int main()
{
    while(scanf("%d%d",&n,&q)!=EOF)
    {
        init();
        Insert(0,n);
        char op[20];
        int x,y,z;
        while(q--)
        {
            scanf("%s",op);
            if(op[0]=='I')
            {
                scanf("%d%d",&x,&y);
                Insert(x,y);
            }
            else if(op[0]=='D')
            {
                scanf("%d%d",&x,&y);
                Delete(x,y);
            }
            else if(op[2]=='K')
            {
                scanf("%d%d%d",&x,&y,&z);
                MakeSame(x,y,z);
            }
            else if(op[0]=='R')
            {
                scanf("%d%d",&x,&y);
                Reverse(x,y);
            }
            else if(op[0]=='G')
            {
                scanf("%d%d",&x,&y);
                printf("%d\n",GetSum(x,y));
            }
            else if(op[2]=='X')
                printf("%d\n",MaxSum());
        }
    }
    return 0;
}
 

///因为被一道题卡了内存(估计原因是在那个oj里面,指针是8个字节),写了一个用数组的,当模板用。。。2015.02.18

<pre name="code" class="cpp">#include<stdio.h>
#include<algorithm>
using namespace std;
const int maxn = 5e5+10;
const int inf = 1e8+1000;
#define ls c[x][0]
#define rs c[x][1]
#define Key_val c[c[root][1]][0]
int p[maxn],c[maxn][2],root;
int key[maxn],sz[maxn],num[maxn],sum[maxn];
int mx[maxn],lx[maxn],rx[maxn];
bool rev[maxn],same[maxn];
int a[maxn],pool[maxn],tot1,tot2;
int n,q;
bool getlr(int r){return c[p[r]][1]==r;}
int link(int r,int w,int x){c[r][w]=x;if(x)p[x]=r;return r;}

void NewNode(int &r,int v,int per)
{
    if(tot2) r = pool[tot2--];
    else r = ++tot1;
    p[r] = per;
    sz[r] = num[r] = 1;
    key[r] = sum[r] = mx[r] = lx[r] = rx[r] = v;
    same[r] = rev[r] = 0;
    c[r][0] = c[r][1] = 0;
}

void Updata_same(int x,int v)
{
    if(!x) return;
    same[x] = 1; key[x] = v;
    sum[x] = v*sz[x];
    lx[x] = rx[x] = mx[x] = max(v, sum[x]);
}

void Updata_rev(int x)
{
    if(!x) return;
    swap(ls,rs);
    swap(lx[x],rx[x]);
    rev[x] ^= 1;
}

void pushup(int x)
{
    sz[x] = sz[ls] + sz[rs] + num[x];
    sum[x] = sum[ls] + sum[rs] + key[x];
    lx[x] = max(lx[ls], sum[ls] + key[x] + max(0, lx[rs]));
    rx[x] = max(rx[rs], sum[rs] + key[x] + max(0, rx[ls]));
    mx[x] = max(0, rx[ls]) + key[x] + max(0, lx[rs]);
    mx[x] = max(mx[x], max(mx[ls], mx[rs]));
}

void pushdown(int x)
{
    if(same[x])
    {
        Updata_same(ls, key[x]);
        Updata_same(rs, key[x]);
        same[x] = 0;
    }
    if(rev[x])
    {
        Updata_rev(ls);
        Updata_rev(rs);
        rev[x] = 0;
    }
}

void dfs(int x)
{
    if(!x) return;
    pushdown(x);
    dfs(ls);
    printf("%d sz:%d sum:%d\n",key[x],sz[x],sum[x]);
    dfs(rs);
}

void test()
{
    dfs(root);
    puts("");
}

void Build(int &x,int l,int r,int per)
{
    if(l > r) return;
    int mid = (l+r)/2;
    NewNode(x, a[mid], per);
    Build(ls,l,mid-1,x);
    Build(rs,mid+1,r,x);
    pushup(x);
}

void rot(int x)
{
    int z = p[p[x]], o = getlr(x);
    link(x,!o,link(p[x],o,c[x][!o]));
    pushup(p[x]);
    if(z) link(z,c[z][1]==p[x],x);
    else p[x]=0, root=x;
}
void splay(int x,int tar)
{
    pushdown(x);
    while(p[x]!=tar)
    {
        if(p[p[x]]!=tar)pushdown(p[p[x]]);
        pushdown(p[x]);
        pushdown(x);
        if(p[p[x]]!=tar)getlr(x)==getlr(p[x])?rot(p[x]):rot(x);
        rot(x);
    }
    pushup(x);
}

void select(int k, int tar)
{
    int x = root;
    pushdown(x);
    while(!(sz[ls]<k && sz[ls] + num[x] >= k))
    {
        if(k <= sz[ls])
            x = ls;
        else
        {
            k -= sz[ls] + num[x];
            x = rs;
        }
        pushdown(x);
    }
    splay(x, tar);
}

void Insert(int pos,int tot)
{
    for(int i=0;i<tot;i++) scanf("%d",&a[i]);
    select(pos+1,0);
    select(pos+2,root);
    Build(Key_val,0,tot-1,c[root][1]);
    splay(Key_val,0);
}

void earse(int x)
{
    if(!x) return;
    pool[++tot2] = x;
    earse(ls);
    earse(rs);
}

void Delete(int pos,int tot)
{
    select(pos,0);
    select(pos+tot+1,root);
    earse(Key_val);
    Key_val = 0;
    splay(c[root][1], 0);
}

void Reverse(int pos,int tot)
{
    select(pos,0);
    select(pos+tot+1,root);
    Updata_rev(Key_val);
    splay(Key_val,0);
}

void MakeSame(int pos,int tot,int v)
{
    select(pos,0);
    select(pos+tot+1,root);
    Updata_same(Key_val, v);
    splay(Key_val,0);
}

int GetSum(int pos,int tot)
{
    select(pos,0);
    select(pos+tot+1, root);
    return sum[Key_val];
}

int MaxSum()
{
    return mx[root];
}

void init()
{
    root = tot1 = tot2 = 0;
    lx[0] = rx[0] = mx[0] = -inf;
    NewNode(root,-inf,0);
    NewNode(c[root][1],-inf,root);
    pushup(root);
}

int main()
{
    while(scanf("%d%d",&n,&q)!=EOF)
    {
        init();
        Insert(0,n);
        char op[20];
        int x,y,z;
        while(q--)
        {
            scanf("%s",op);
            if(op[0]=='I')
            {
                scanf("%d%d",&x,&y);
                Insert(x,y);
            }
            else if(op[0]=='D')
            {
                scanf("%d%d",&x,&y);
                Delete(x,y);
            }
            else if(op[2]=='K')
            {
                scanf("%d%d%d",&x,&y,&z);
                MakeSame(x,y,z);
            }
            else if(op[0]=='R')
            {
                scanf("%d%d",&x,&y);
                Reverse(x,y);
            }
            else if(op[0]=='G')
            {
                scanf("%d%d",&x,&y);
                printf("%d\n",GetSum(x,y));
            }
            else if(op[2]=='X')
                printf("%d\n",MaxSum());
        }
    }
    return 0;
}

                
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值