luogu P5350 序列 题解

P5350 序列

题目大意

详见题目描述。

解题思路

操作1

先利用 split 操作得到左右端点的迭代器,然后直接暴力遍历即可。记得不要忘记取模

操作2

ODT 基础操作,区间推平,这里不作详细
解释。

操作3

跟操作1类似,暴力遍历即可。

操作4

先将区间 [ l 2 , r 2 ] [l_2,r_2] [l2,r2] 删掉,然后设 d i s t a n c e = l 2 − l 1 distance=l_2-l_1 distance=l2l1,暴力遍历区间 [ l 1 , r 1 ] [l_1,r_1] [l1,r1],将里面的每个小区间的范围加上 v a l val val 并加入到 s e t set set 中即可。

操作5

我们利用 swap 的原理,先把区间 [ l 1 , r 1 ] [l_1,r_1] [l1,r1] 复制给 n n n 后面的一个区间,
再把区间 [ l 2 , r 2 ] [l_2,r_2] [l2,r2]复制给区间 [ l 1 , r 1 ] [l_1,r_1] [l1,r1],最后把第一步中的区间复制给区间 [ l 2 , r 2 ] [l_2,r_2] [l2,r2]

操作6

利用判断回文串的原理。首先遍历这个区间,假设当前区间的下标分别为 l 1 l_1 l1 r 1 r_1 r1,那它反转后对应得下标为 l + r − r 1 l+r-r_1 l+rr1 l + r − l 1 l+r-l_1 l+rl1. 我们拿个数组存一下这些操作,遍历完之后再把它们插入即可。

最后将 1 1 1~ n n n 遍历输出即可。

代码实现

#include
using namespace std;
int n,m,v[300000+10];
const long long mod=1e9+7;
struct node
{
    int l,r;
    mutable long long v;
    node(int L,int R=-1,int V=0)
    {
        l=L,r=R,v=V;
    }
    bool operator<(const node &a) const
    {
        return l<a.l;
    }
};
set<node> a;
#define at set<node>::iterator
struct operate
{
    int l,r;
    long long v;
}op[300000+10];
at split(int pos)
{
    at it=a.lower_bound(pos);
    if(it!=a.end()&&it->l==pos)
        return it;
    it--;
    int l=it->l;
    int r=it->r;
    int v=it->v;
    a.erase(it);
    a.insert(node(l,pos-1,v));
    return a.insert(node(pos,r,v)).first;
}
int read()
{
    int s=0,w=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')
            w=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
        s=s*10+(ch-'0'),ch=getchar();
    return s*w;
}
void work1()
{
    int l=read(),r=read();
    long long ans=0;
    at itr=split(r+1);
    at itl=split(l);
    for(at it=itl;it!=itr;++it)
        ans=(ans+(it->r-it->l+1)*it->v)%mod;
    printf("%lld\n",ans);
}
void work2(int l,int r,int v)
{
    at itr=split(r+1);
    at itl=split(l);
    a.erase(itl,itr);
    a.insert(node(l,r,v));
    return ;
}
void work3()
{
    int l=read(),r=read(),v=read();
    at itr=split(r+1);
    at itl=split(l);
    for(at it=itl;it!=itr;++it)
        it->v=(it->v+v)%mod;
    return ;
}
void work4(int l1,int r1,int l2,int r2)
{
    int l=0;
    at itr=split(r1+1);
    at itl=split(l1);
    int val=l2-l1;
    for(at it=itl;it!=itr;++it)
        op[++l]=(operate){it->l+val,it->r+val,it->v};
    itr=split(r2+1);
    itl=split(l2);
    a.erase(itl,itr);
    for(int i=1;i<=l;++i)
        a.insert(node(op[i].l,op[i].r,op[i].v));
    return ;
}
void work5()
{
    int l1=read(),r1=read(),l2=read(),r2=read();
    work4(l1,r1,n+1,n+r1-l1+1);
    work4(l2,r2,l1,r1);
    work4(n+1,n+r1-l1+1,l2,r2);
    return ;
}
void work6()
{
    int l=read(),r=read(),siz=0;
    at itr=split(r+1);
    at itl=split(l);
    for(at it=itl;it!=itr;++it)
        op[++siz]=(operate){l+r-it->r,l+r-it->l,it->v};
    a.erase(itl,itr);
    for(int i=1;i<=siz;++i)
        a.insert(node(op[i].l,op[i].r,op[i].v));
    return ;
}
int main()
{
    n=read(),m=read();
    for(int i=1;i<=n;++i)
        v[i]=read(); 
    for(int i=1;i<=n;++i)
    {
        int l=i,r=i;
        while(r+1<=n&&v[r+1]==v[l])
            r++;
        a.insert(node(l,r,v[l]));
        i=r;
    }
    a.insert(node(n+1,n+10,1e9+8));
    for(int i=1;i<=m;++i)
    {   
        int opt=read();
        if(opt==1)
            work1();
        if(opt==2)
        {
            int l=read(),r=read(),v=read();
            work2(l,r,v);
        }
        if(opt==3)
            work3();
        if(opt==4)
        {
            int l1=read(),r1=read(),l2=read(),r2=read();
            work4(l1,r1,l2,r2);
        } 
        if(opt==5)
            work5();
        if(opt==6)
            work6();
    }
    at itr=split(n+1);
    for(at it=a.begin();it!=itr;++it)
    {
        for(int i=it->l;i<=it->r;++i)
            printf("%lld ",it->v%mod);
    }
    return 0;
}

你可能感兴趣的:(题解,c++)