Solution P2572 [[SCOI2010] sequence operation]

Move Luogu blog here

Move Luogu blog here

Move Luogu blog here

Important things are to be repeated for 3 times

This question is too pitiful. I did it for a whole day. I found out that pushup() was wrong after finding the wrong one. At the beginning, I swore that pushup() was right, and the result was pushup() the most

The difficulty of this problem is quite regular, that is, there are many details to deal with, and it will take a long time to find a mistake.

How do you do it?

First of all, there are two kinds of changes (three changes) and two inquiries. At the beginning, I opened two lazy marks, but in fact, they are not used, which is more troublesome. Just a lazy flag is enough.

For each modification, we will discuss the classification: when opt0||||||||||||||||||||||||||||||||||||||||;
downdate() is similar to the above;

Then we must pay attention to pushup(), which is a very short function, but it is very important to deal with it properly.

What about 1 in a row?

This method is quite ingenious. You can use a pre to record the maxr of the left interval, update it up, find the maxl of the right interval, and then compare it with maxx (because the query interval may not be included by an interval in a segment tree, it may be divided into two queries).

Code (where you don't understand, you should understand the code after reading it. The code is easy to understand. Read it patiently):

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ls id<<1
#define rs id<<1|1
using namespace std;
const int N=100000+10;
int n,m,a[N],ans=0,pre;
struct node
{
    int left,right,sign,sum,maxx,maxl,maxr,maxl0,maxr0,maxx0;
}tree[N*4];
void pushup(int id)//Hateful function
{
    tree[id].sum=tree[ls].sum+tree[rs].sum;
    tree[id].maxl=tree[ls].maxl;tree[id].maxl0=tree[ls].maxl0;
    if(tree[id].maxl==tree[ls].right-tree[ls].left+1)tree[id].maxl+=tree[rs].maxl;
    if(tree[id].maxl0==tree[ls].right-tree[ls].left+1)tree[id].maxl0+=tree[rs].maxl0;
    tree[id].maxr=tree[rs].maxr;tree[id].maxr0=tree[rs].maxr0;
    if(tree[id].maxr==tree[rs].right-tree[rs].left+1)tree[id].maxr+=tree[ls].maxr;
    if(tree[id].maxr0==tree[rs].right-tree[rs].left+1)tree[id].maxr0+=tree[ls].maxr0;
    tree[id].maxx=max(tree[ls].maxx,max(tree[rs].maxx,tree[ls].maxr+tree[rs].maxl));
    tree[id].maxx0=max(tree[ls].maxx0,max(tree[rs].maxx0,tree[ls].maxr0+tree[rs].maxl0));
}
void built(int id,int l,int r)
{
    tree[id].left=l,tree[id].right=r,tree[id].sign=-1;
    if(l==r)
    {
        tree[id].maxl=tree[id].maxr=tree[id].maxx=tree[id].sum=a[l];
        tree[id].maxl0=tree[id].maxr0=tree[id].maxx0=(a[l]^1);
        return;
    }
    int mid=(l+r)>>1;
    built(ls,l,mid),built(rs,mid+1,r);pushup(id);
}
void change(int id)
{
    swap(tree[id].maxl,tree[id].maxl0);swap(tree[id].maxr,tree[id].maxr0);swap(tree[id].maxx,tree[id].maxx0);
    tree[id].sum=tree[id].right-tree[id].left+1-tree[id].sum;
}
void downdate(int id)
{
    if(tree[id].sign<=1&&tree[id].sign>=0)
    {
        int tmp;
        tmp=(tree[ls].right-tree[ls].left+1);
        tree[ls].sign=tree[id].sign;
        tree[ls].maxl=tree[ls].maxr=tree[ls].maxx=tree[ls].sum=tmp*tree[id].sign;
        tree[ls].maxl0=tree[ls].maxr0=tree[ls].maxx0=tmp*(tree[id].sign^1);
        tmp=(tree[rs].right-tree[rs].left+1);
        tree[rs].sign=tree[id].sign;
        tree[rs].maxl=tree[rs].maxr=tree[rs].maxx=tree[rs].sum=tmp*tree[id].sign;
        tree[rs].maxl0=tree[rs].maxr0=tree[rs].maxx0=tmp*(tree[id].sign^1);
    }
    else if(tree[id].sign==2)
    {
        if(tree[ls].sign<=1&&tree[ls].sign>=0)
        {
            int tmp=(tree[ls].right-tree[ls].left+1);
            tree[ls].maxl=tree[ls].maxr=tree[ls].maxx=tree[ls].sum=tmp*(tree[ls].sign^1);
            tree[ls].maxl0=tree[ls].maxr0=tree[ls].maxx0=tmp*tree[ls].sign;
            tree[ls].sign^=1;
        }
        else if(tree[ls].sign==-1)
        {
            change(ls);tree[ls].sign=2;
        }
        else if(tree[ls].sign==2)
        {
            change(ls);tree[ls].sign=-1;
        }
        if(tree[rs].sign<=1&&tree[rs].sign>=0)
        {
            int tmp=(tree[rs].right-tree[rs].left+1);
            tree[rs].maxl=tree[rs].maxr=tree[rs].maxx=tree[rs].sum=tmp*(tree[rs].sign^1);
            tree[rs].maxl0=tree[rs].maxr0=tree[rs].maxx0=tmp*tree[rs].sign;
            tree[rs].sign^=1;
        }
        else if(tree[rs].sign==-1)
        {
            change(rs);tree[rs].sign=2;
        }
        else if(tree[rs].sign==2)
        {
            change(rs);tree[rs].sign=-1;
        }
    }tree[id].sign=-1;
}
void update(int id,int l,int r,int opt)
{
    if(tree[id].left>r||tree[id].right<l)return;
    if(tree[id].left>=l&&tree[id].right<=r)
    {
        if(opt==0||opt==1)
        {
            int tmp=(tree[id].right-tree[id].left+1);tree[id].sign=opt;
            tree[id].maxl=tree[id].maxr=tree[id].maxx=tree[id].sum=tmp*tree[id].sign;
            tree[id].maxl0=tree[id].maxr0=tree[id].maxx0=tmp*(tree[id].sign^1);
        }
        else if(opt==2)
        {
            if(tree[id].sign==2)
            {
                change(id);tree[id].sign=-1;
            }
            else if(tree[id].sign<=1&&tree[id].sign>=0)
            {
                int tmp=(tree[id].right-tree[id].left+1);tree[id].sign^=1;
                tree[id].maxl=tree[id].maxr=tree[id].maxx=tree[id].sum=tmp*tree[id].sign;
                tree[id].maxl0=tree[id].maxr0=tree[id].maxx0=tmp*(tree[id].sign^1);
            }
            else if(tree[id].sign==-1)
            {
                change(id);tree[id].sign=2;
            }
        }
        return;
    }
    if(tree[id].sign>=0)downdate(id);
    update(ls,l,r,opt);update(rs,l,r,opt);pushup(id);
}
int querysum(int id,int l,int r)
{
    if(tree[id].left>r||tree[id].right<l)return 0;
    if(tree[id].left>=l&&tree[id].right<=r)return tree[id].sum;
    if(tree[id].sign>=0)downdate(id);
    int tmp=querysum(ls,l,r)+querysum(rs,l,r);
    return tmp;
}
void querymaxx(int id,int l,int r)
{
    if(tree[id].left>r||tree[id].right<l)return;
    if(tree[id].left>=l&&tree[id].right<=r)
    {
        ans=max(ans,max(tree[id].maxx,pre+tree[id].maxl));
        if(tree[id].sum==tree[id].right-tree[id].left+1) pre+=tree[id].sum;
        else pre=tree[id].maxr;//Cleverly pre
        return;
    }
    if(tree[id].sign>=0)downdate(id);
    querymaxx(ls,l,r);querymaxx(rs,l,r);
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    built(1,1,n);
    for(int i=1;i<=m;i++)
    {
        int x,y,opt;
        scanf("%d%d%d",&opt,&x,&y);x++,y++;
        if(opt<=2)update(1,x,y,opt);
        if(opt==3)printf("%d\n",querysum(1,x,y));
        if(opt==4)ans=0,pre=0,querymaxx(1,x,y),printf("%d\n",ans);
    }
}
Published 2 original articles, won praise 3, visited 341
Private letter follow

Posted on Fri, 07 Feb 2020 11:22:07 -0500 by PAZII