BZOJ3236: [Ahoi2013]作业

Posted Star_Feel

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ3236: [Ahoi2013]作业相关的知识,希望对你有一定的参考价值。

【传送门:BZOJ3236


简要题意:

  给出一个n个数的序列,序列中的数范围为1到n,给出m个操作,每个操作输入l,r,a,b,输出l到r中权值为a到b的数的个数和l到r中权值为a到b的数的种类


题解:

  BZOJ3809的添加版,其实差不多

  只是在BZOJ3809的做法上多加一个求个数和的数组就可以了


参考代码:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
struct node
{
    int l,r,a,b,id,d1,d2;
}q[1100000];
int s[110000];
int bl[1100],br[1100],belong[110000];
bool cmp1(node n1,node n2)
{
    if(belong[n1.l]<belong[n2.l]) return true;
    if(belong[n1.l]>belong[n2.l]) return false;
    if(belong[n1.l]==belong[n2.l])
    {
        if(n1.r<n2.r) return true;
        if(n1.r>n2.r) return false;
    }
    return false;
}
bool cmp2(node n1,node n2)
{
    return n1.id<n2.id;
}
int d1[1100],d2[1100],sum[110000];
void add(int x)
{
    sum[x]++;d2[belong[x]]++;
    if(sum[x]==1) d1[belong[x]]++;
}
void del(int x)
{
    sum[x]--;d2[belong[x]]--;
    if(sum[x]==0) d1[belong[x]]--;
}
int solve1(int x,int y)
{
    int bx=belong[x],by=belong[y];
    int ans=0;
    if(bx==by)
    {
        for(int i=x;i<=y;i++)
        {
            if(sum[i]>0) ans++;
        }
        return ans;
    }
    for(int i=bx+1;i<=by-1;i++) ans+=d1[i];
    for(int i=x;i<=br[bx];i++) if(sum[i]>0) ans++;
    for(int i=bl[by];i<=y;i++) if(sum[i]>0) ans++;
    return ans;
}
int solve2(int x,int y)
{
    int bx=belong[x],by=belong[y];
    int ans=0;
    if(bx==by)
    {
        for(int i=x;i<=y;i++) ans+=sum[i];
        return ans;
    }
    for(int i=bx+1;i<=by-1;i++) ans+=d2[i];
    for(int i=x;i<=br[bx];i++) ans+=sum[i];
    for(int i=bl[by];i<=y;i++) ans+=sum[i];
    return ans;
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&s[i]);
    int block=int(sqrt(n));
    for(int i=1;i<=n;i++)
    {
        int t=(i-1)/block+1;
        belong[i]=t;
        if(bl[t]==0) br[t-1]=i-1,bl[t]=i;
    }
    br[belong[n]]=n;
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d%d",&q[i].l,&q[i].r,&q[i].a,&q[i].b);
        q[i].id=i;
    }
    sort(q+1,q+m+1,cmp1);
    memset(sum,0,sizeof(sum));
    memset(d1,0,sizeof(d1));
    memset(d2,0,sizeof(d2));
    int l=1,r=0;
    for(int i=1;i<=m;i++)
    {
        while(l>q[i].l){l--;add(s[l]);}
        while(l<q[i].l){del(s[l]);l++;}
        while(r>q[i].r){del(s[r]);r--;}
        while(r<q[i].r){r++;add(s[r]);}
        q[i].d1=solve1(q[i].a,q[i].b);
        q[i].d2=solve2(q[i].a,q[i].b);
    }
    sort(q+1,q+m+1,cmp2);
    for(int i=1;i<=m;i++) printf("%d %d\\n",q[i].d2,q[i].d1);
    return 0;
}

 

以上是关于BZOJ3236: [Ahoi2013]作业的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ3236:[AHOI2013]作业——题解

BZOJ3236: [Ahoi2013]作业

bzoj 3236: [Ahoi2013]作业(缺线段树)

BZOJ3236: [Ahoi2013]作业 树状数组维护 莫队

Bzoj3238: [Ahoi2013]差异

[BZOJ3238][Ahoi2013]差异