LG P6749 『MdOI R3』Yoshino

Description

Yoshino 给了你一个长度为$n$的序列,第$i$项为 $a_i$

现在 Yoshino 会对数列进行 $m$ 次操作。

操作分成两种:

  • $1\ l\ r\ x$Yoshino 把数列下标在 $[l,r]$ 区间内的数修改为了一个从 $x$ 开始公差为 $1$的等差数列。
  • $2$ Yoshino 需要查询整个数列中的逆序对个数。逆序对的定义为数对 $(i,j)$ 满足$i < j$ 且 $a_i > a_j$

Solution

考虑每次修改对答案产生的贡献,于是开始时用树状数组先统计初始的答案

每次的修改区间内部不会产生影响,考虑对修改区间两侧的数产生的影响

用数组记录对于修改区间中的数,修改区间前面的部分中有多少数大于第$i$位上的数,对其差分

用数组记录对于修改区间后面的部分,有多少修改区间中的数大于$i$,对其差分

每次更新数组和答案即可

虽然复杂度不对但是可过

正解:线段树套珂朵莉树

#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int n,m,a[30005],bits[30005],cnt[30005],ans,great[30005],sav[30005],maxx,L[30005],R[30005],X[30005],O[30005];
inline int read()
{
    int w=0,f=1;
    char ch=0;
    while(ch<'0'||ch>'9')
    {
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        w=(w<<1)+(w<<3)+ch-'0';
        ch=getchar();
    }
    return w*f;
}
inline void write(int x)
{
    if(x>9)
    {
        write(x/10);
    }
    putchar(x%10+'0');
}
inline void add(int pos)
{
    while(pos<=maxx)
    {
        bits[pos]++;
        pos+=pos&-pos;
    }
}
inline int query(int pos)
{
    int ret=0;
    while(pos)
    {
        ret+=bits[pos];
        pos-=pos&-pos;
    }
    return ret;
}
int main()
{
    n=read();
    m=read();
    for(register int i=1;i<=n;i++)
    {
        a[i]=read();
        maxx=max(maxx,a[i]);
    }
    for(register int i=1;i<=n;i++)
    {
        cnt[i]=i-1-query(a[i]);
        ans+=cnt[i];
        add(a[i]);
    }
    for(register int i=1;i<=m;i++)
    {
        O[i]=read();
        if(O[i]==1)
        {
            L[i]=read();
            R[i]=read();
            X[i]=read();
            maxx=max(maxx,X[i]+R[i]-L[i]);
        }
    }
    for(register int i=1;i<=m;i++)
    {
        int opt=O[i];
        if(opt==1)
        {
            for(int j=0;j<=maxx;j++)
            {
                great[j]=sav[j]=0; 
            }
            int l=L[i],r=R[i],x=X[i],vr=x+r-l;
            for(register int j=l;j<=r;j++)
            {
                ans-=cnt[j];
                ++sav[a[j]-1];
                a[j]=x+j-l;
            }
            for(register int j=1;j<l;j++)
            {
                if(a[j]>vr)
                {
                    ++great[vr];
                }
                else
                {
                    ++great[a[j]-1];
                }
            }
            for(register int j=vr;j>=x;j--)
            {
                great[j]+=great[j+1];
                ans+=great[j];
                cnt[j-x+l]=great[j];
            }
            for(register int j=maxx;j;j--)
            {
                sav[j]+=sav[j+1];
            }
            for(register int j=r+1;j<=n;j++)
            {
                cnt[j]-=sav[a[j]];
                ans-=sav[a[j]];
                cnt[j]+=max(0,min(vr-a[j],vr-x+1));
                ans+=max(0,min(vr-a[j],vr-x+1));
            }
        }
        else
        {
            write(ans);
            printf("\n");
        }
    }
    return 0;
}
Yoshino

 

posted @ 2020-08-16 21:23  QDK_Storm  阅读(224)  评论(0)    收藏  举报