CDOJ 1157 数列(seq) (分块)

题意:给出一个数列,两种操作
1.修改操作:把数列中第i个数改为x
2.询问操作:给定一个位置i,问数列中有多少个位置j ( j>i ),满足位置i与位置j间所有的数都不超过Ai与Aj的较大值。

简单来说,操作2分为两部分
1.位置i右边相邻连续的比它小的数字个数
2.位置i右边不减序列长度
直接将数列分块,分块暴力维护和求解答案
第一部分询问做法:记录块中最大值为多少,如果整个块中值小于当前值,则答案直接加上一个block,一直到找到第一个大于 a[i] 的值
第二部分询问做法:将每个块中的上升序列都用vector保存下来,使用时二分查找答案

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#pragma comment(linker, "/STACK:1024000000,1024000000");

using namespace std;

#define INF 0x3f3f3f3f
#define maxn 500005

int n,m;
int a[maxn];
int block,num,belong[maxn],l[maxn],r[maxn],MX[maxn];
vector<int>que[maxn];

void nex_init()
{
    for(int i=1; i<=num; i++)
    {
        que[i].clear();
    }
}

void init()
{
    block=sqrt(n);
    num=n/block;
    if(n%block) num++;
    for(int i=1; i<=n; i++)
    {
        belong[i]=(i-1)/block+1;
    }
    for(int i=1; i<=num; i++)
    {
        l[i]=block*(i-1)+1;
        r[i]=i*block;
    }
    r[num]=n;
    for(int i=1; i<=num; i++)
    {
        int mx=a[l[i]];
        for(int j=l[i]; j<=r[i]; j++)
        {
            if(a[j]>=mx)
            {
                que[i].push_back(a[j]);
                mx=a[j];
            }
        }
        MX[i]=mx;
    }
}

void update(int x,int val)
{
    a[x]=val;
    que[belong[x]].clear();
    int mx=a[l[belong[x]]];
    for(int i=l[belong[x]]; i<=r[belong[x]]; i++)
    {
        if(a[i]>=mx)
        {
            que[belong[x]].push_back(a[i]);
            mx=a[i];
        }
    }
    MX[belong[x]]=mx;
}

int part_A(int x)
{
    int sum=0;
    int pos=x+1;
    while(pos<=n&&pos<=r[belong[x]])
    {
        if(a[pos++]<=a[x]) sum++;
        else return sum;
    }
    if(pos>n) return sum;
    pos=belong[x]+1;
    while(pos<=num&&MX[pos]<=a[x])
    {
        sum+=r[pos]-l[pos]+1;
        pos++;
    }
    if(pos>num) return sum;
    pos=l[pos];
    while(pos<=n&&a[pos]<=a[x])
    {
        sum++,pos++;
    }
    return sum;
}

int part_B(int x)
{
    int ans=0;
    if(x>n) return 0;
    int mx=a[x];
    for(int i=x; i<=r[belong[x]]; i++)
    {
        if(mx<=a[i]) ans++,mx=a[i];
    }
    for(int i=belong[x]+1; i<=num; i++)
    {
        if(MX[i]continue;
        int pos=lower_bound(que[i].begin(),que[i].end(),mx)-que[i].begin();
        ans+=(int)que[i].size()-pos;
        mx=MX[i];
    }
    return ans;
}

int query(int x)
{
    int ans=0;
    ans+=part_A(x);
    ans+=part_B(x+ans+1);
    return ans;
}

int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        for(int i=1; i<=n; i++) scanf("%d",&a[i]);
        init();
        while(m--)
        {
            char op[3];
            scanf("%s",op);
            if(op[0]=='Q')
            {
                int x;
                scanf("%d",&x);
                printf("%d\n",query(x));
            }
            else
            {
                int x,y;
                scanf("%d%d",&x,&y);
                update(x,y);
            }
        }
        nex_init();
    }
    return 0;
}

你可能感兴趣的:(===数据结构===,分块)