bzoj1500 [NOI2005]维修数列

题目链接:bzoj1500

这是一篇补档博客

讲真,出题人出这种看起来十分模板,几乎没有思维难度,但是细节贼多,考场上几乎不可能写高分的题目出出来的心态是什么

就这个题,前四个操作几乎是清一色的画风——把要操作的东西单独建成一颗平衡树(splay),然后各种左右儿子找

第五个操作直接维护,第六个类似于分治的时候,维护左端点起始最大值、右端点起始最大值、包含该点及其子树的最大值。就做完了,哦,为了内存不炸回收一下delete的节点编号以下次使用

但是细节巨多啊。。。几乎是完全不可能在考场上调出来啊

所以这种题真的只适合养性了吧。。。

献上6k代码

#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<vector>
#include<queue>
#include<map>
using namespace std;
#define int long long
const int maxd=1000000007,N=100000;
const double pi=acos(-1.0);
typedef long long ll;
struct node{
    int ch[2],fa,same,rev;
    ll sum,lsum,val,rsum,siz,maxsum;
    void init(int v)
    {
        siz=1;val=v;sum=v;
        same=0;rev=0;
        ch[0]=0;ch[1]=0;
        lsum=max(v,0ll);rsum=lsum;maxsum=v;
    }
}tree[600000];
queue<int> q;
int n,qsiz,tot=0,root=0,a[600000];
char s[100];

int read()
{
    int x=0,f=1;char ch=getchar();
    while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
    while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
    return x*f;
}

void pushup(int x)
{
    int l=tree[x].ch[0],r=tree[x].ch[1];
    tree[x].siz=tree[l].siz+tree[r].siz+1;
    tree[x].sum=tree[l].sum+tree[r].sum+tree[x].val;
    tree[x].maxsum=max(tree[l].maxsum,max(tree[r].maxsum,tree[l].rsum+tree[x].val+tree[r].lsum));
    tree[x].lsum=max(tree[l].lsum,tree[l].sum+tree[x].val+tree[r].lsum);
    tree[x].rsum=max(tree[r].rsum,tree[r].sum+tree[x].val+tree[l].rsum);
}

void pushdown(int x)
{
    int l=tree[x].ch[0],r=tree[x].ch[1];
    if (tree[x].same)
    {
        tree[x].same=0;tree[x].rev=0;
        if (l)
        {
            tree[l].same=1;tree[l].val=tree[x].val;tree[l].sum=tree[x].val*tree[l].siz;
        }
        if (r)
        {
            tree[r].same=1;tree[r].val=tree[x].val;tree[r].sum=tree[x].val*tree[r].siz;
        }
        if (tree[x].val>=0)
        {
            if (l) tree[l].lsum=tree[l].rsum=tree[l].maxsum=tree[l].sum;
            if (r) tree[r].lsum=tree[r].rsum=tree[r].maxsum=tree[r].sum;
        }
        else 
        {
            if (l) {tree[l].lsum=0;tree[l].rsum=0;tree[l].maxsum=tree[x].val;}
            if (r) {tree[r].lsum=0;tree[r].rsum=0;tree[r].maxsum=tree[x].val;}
        }
    }
    if (tree[x].rev)
    {
        tree[x].rev^=1;
        if (l) tree[l].rev^=1;
        if (r) tree[r].rev^=1;
        swap(tree[l].lsum,tree[l].rsum);swap(tree[r].lsum,tree[r].rsum);
        swap(tree[l].ch[0],tree[l].ch[1]);swap(tree[r].ch[0],tree[r].ch[1]);
    }
}

void rotate(int x)
{
    int y=tree[x].fa,z=tree[y].fa,k=(tree[y].ch[1]==x);
    tree[z].ch[tree[z].ch[1]==y]=x;
    tree[x].fa=z;
    tree[y].ch[k]=tree[x].ch[k^1];
    tree[tree[x].ch[k^1]].fa=y;
    tree[x].ch[k^1]=y;tree[y].fa=x;
    pushup(y);pushup(x);
}

void splay(int x,int goal)
{
    while (tree[x].fa!=goal)
    {
        int y=tree[x].fa,z=tree[y].fa;
        if (z!=goal)
        {
            if ((tree[y].ch[1]==x)^(tree[z].ch[1]==y)) rotate(x);else rotate(y);
        }
        rotate(x);
    }
    if (!goal) root=x;
}

int rnk(int k)
{
    int now=root;
    //cout << k << endl;
    while (now)
    {
        pushdown(now);
        if (tree[tree[now].ch[0]].siz+1<k) 
            {k-=(tree[tree[now].ch[0]].siz+1);now=tree[now].ch[1];}
        else if (tree[tree[now].ch[0]].siz+1==k) return now;
        else now=tree[now].ch[0];
        //cout << now << " " << k << endl;
    }
}

int build(int l,int r,int fa)
{
    if (l>r) return 0;
    int mid=(l+r)>>1,now=q.front();q.pop();qsiz--;
    if (l==r)
    {
        tree[now].fa=fa;
        tree[now].init(a[mid]);
        return now;
    }
    tree[now].val=a[mid];tree[now].maxsum=a[mid];tree[now].fa=fa;
    tree[now].ch[0]=build(l,mid-1,now);
    tree[now].ch[1]=build(mid+1,r,now);
    pushup(now);
    return now;
}

void clr(int x)
{
    tree[x].maxsum=-maxd;
    tree[x].fa=0;tree[x].ch[0]=0;tree[x].ch[1]=0;
    tree[x].lsum=0;tree[x].rsum=0;tree[x].siz=0;tree[x].rev=0;
    tree[x].same=0;
}

void reuse(int x)
{
    if (!x) return;
    q.push(x);qsiz++;
    if (tree[x].ch[0]) reuse(tree[x].ch[0]);
    if (tree[x].ch[1]) reuse(tree[x].ch[1]);
    clr(x);
}

void insert()
{
    int pos=read(),tot=read(),i;
    if (!tot) return;
    for (i=1;i<=tot;i++) a[i]=read();
    int l=rnk(pos+1),r=rnk(pos+2);
    splay(l,0);splay(r,l);
    tree[r].ch[0]=build(1,tot,r);
    pushup(r);pushup(l);
}

void del()
{
    int pos=read(),tot=read(); 
    if (!tot) return;
    int l=rnk(pos),r=rnk(pos+tot+1);
    //cout << l << " " << r << endl;
    splay(l,0);splay(r,l);
    reuse(tree[r].ch[0]);
    tree[r].ch[0]=0;
    pushup(r);pushup(l);
}

void rever()
{
    int pos=read(),tot=read();
    if (!tot) return;
    int l=rnk(pos),r=rnk(pos+tot+1);
    splay(l,0);splay(r,l);
    int now=tree[r].ch[0];
    if (!tree[now].same)
    {
        tree[now].rev^=1;
        swap(tree[now].ch[0],tree[now].ch[1]);
        swap(tree[now].lsum,tree[now].rsum);
        pushup(r);pushup(l);
    }
}

void getsum()
{
    int pos=read(),tot=read();
    //if (!tot) return;
    int l=rnk(pos),r=rnk(pos+tot+1);
    splay(l,0);splay(r,l);
    printf("%lld\n",tree[tree[r].ch[0]].sum);
}

void makesame()
{
    int pos=read(),tot=read(),nowval=read();
    //if (!tot) return;
    int l=rnk(pos),r=rnk(pos+tot+1);
    splay(l,0);splay(r,l);
    int now=tree[r].ch[0];
    tree[now].val=nowval;tree[now].same=1;tree[now].sum=tree[now].siz*nowval;
    if (nowval>=0) 
    {
        tree[now].lsum=tree[now].siz*nowval;
        tree[now].rsum=tree[now].lsum;tree[now].maxsum=tree[now].lsum;
    }
    else
    {
        tree[now].lsum=0;tree[now].rsum=0;tree[now].maxsum=nowval;
    }
    pushup(r);pushup(l);
}

void maxsum()
{
    printf("%lld\n",tree[root].maxsum);
}
signed main()
{
    //freopen("a.in","r",stdin);
    //freopen("a.out","w",stdout);
    n=read();int Q=read(),i;qsiz=505000;
    clr(0);
    for (i=1;i<=550000;i++) q.push(i);
    a[1]=-maxd;a[n+2]=-maxd;
    for (i=1;i<=n;i++) a[i+1]=read();
    root=build(1,n+2,0);
    //for (i=1;i<=n+2;i++) cout << tree[i].sum << " ";cout << endl;
    while (Q--)
    {
        scanf("%s",s);int tot;
        if (s[0]=='I') insert();
        else if (s[0]=='D') del();
        else if (s[0]=='R') rever();
        else if (s[0]=='G') getsum();
        else if ((s[0]=='M') && (s[2]=='K')) makesame();
        else if ((s[0]=='M') && (s[2]=='X')) maxsum();
        //for (i=1;i<=20;i++) cout << tree[i].fa << " ";cout << endl;
    }
    return 0;
}
posted @ 2019-05-04 00:45  EncodeTalker  阅读(132)  评论(0编辑  收藏  举报