【BZOJ3809】Gty的二逼妹子序列

3809: Gty的二逼妹子序列

Time Limit: 80 Sec  Memory Limit: 28 MB
Submit: 1627  Solved: 481
[Submit][Status][Discuss]

Description

Autumn和Bakser又在研究Gty的妹子序列了!但他们遇到了一个难题。
 
对于一段妹子们,他们想让你帮忙求出这之内美丽度∈[a,b]的妹子的美丽度的种类数。
 
为了方便,我们规定妹子们的美丽度全都在[1,n]中。
 
给定一个长度为n(1<=n<=100000)的正整数序列s(1<=si<=n),对于m(1<=m<=1000000)次询问“l,r,a,b”,每次输出sl...sr中,权值∈[a,b]的权值的种类数。

 

Input

第一行包括两个整数n,m(1<=n<=100000,1<=m<=1000000),表示数列s中的元素数和询问数。
 
第二行包括n个整数s1...sn(1<=si<=n)。
 
接下来m行,每行包括4个整数l,r,a,b(1<=l<=r<=n,1<=a<=b<=n),意义见题目描述。
 
保证涉及的所有数在C++的int内。
 
保证输入合法。

 

Output

对每个询问,单独输出一行,表示sl...sr中权值∈[a,b]的权值的种类数。

 

Sample Input

10 10
4 4 5 1 4 1 5 1 2 1
5 9 1 2
3 4 7 9
4 4 2 5
2 3 4 7
5 10 4 4
3 9 1 1
1 4 5 9
8 9 3 3
2 2 1 6
8 9 1 4

Sample Output

2
0
0
2
1
1
1
0
1
2

HINT

 

样例的部分解释:

 

5 9 1 2

子序列为4 1 5 1 2

在[1,2]里的权值有1,1,2,有2种,因此答案为2。

 

3 4 7 9

子序列为5 1

在[7,9]里的权值有5,有1种,因此答案为1。

 

4 4 2 5

子序列为1

没有权值在[2,5]中的,因此答案为0。

 

2 3 4 7

子序列为4 5

权值在[4,7]中的有4,5,因此答案为2。

 

建议使用输入/输出优化。

 

 

Source

 

分块+莫队

我们用一个cnt[j]表示第i个询问时j出现次数

我们维护每个块中有多少个元素(第一次?第一次被查询+第一次出现过),我们只要用val数组记录一下某个块有多少个数被维护

假设我们某一次询问移动l,r导致其减成0,我们就更新答案

具体来说我也不是很懂 %一发Flere825

/*To The End Of The Galaxy*/
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<iomanip>
#include<stack>
#include<map>
#include<set>
#include<cmath>
#include<complex>
#define debug(x) cerr<<#x<<"="<<x<<endl
#define INF 0x7f7f7f7f
#define llINF 0x7fffffffffffll
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
inline int init()
{
    int now=0,ju=1;char c;bool flag=false;
    while(1)
    {
        c=getchar();
        if(c=='-')ju=-1;
        else if(c>='0'&&c<='9')
        {
            now=now*10+c-'0';
            flag=true;
        }
        else if(flag)return now*ju;
    }
}
inline long long llinit()
{
    long long now=0,ju=1;char c;bool flag=false;
    while(1)
    {
        c=getchar();
        if(c=='-')ju=-1;
        else if(c>='0'&&c<='9')
        {
            now=now*10+c-'0';
            flag=true;
        }
        else if(flag)return now*ju;
    }
}
struct node
{
    int l,r,a,b,id,ans;
}query[1000101];
int n,m;
int bel[100001];
int block,divi;
int ans;
#define pos(x) (((x-1)/block)+1)
bool cmp(node a,node b)
{
    if(pos(a.l)!=pos(b.l))
    {
        return pos(a.l)<pos(b.l);
    }
    else return a.r<b.r;
}
bool cmpid(node a,node b)
{
    return a.id<b.id;
}
int cnt[100005],val[100005];
int a[100005];
inline void Plus(int p)
{
    cnt[a[p]]++;
    if(cnt[a[p]]==1)val[bel[a[p]]]++;
}
inline void Minus(int p)
{
    cnt[a[p]]--;
    if(cnt[a[p]]==0)val[bel[a[p]]]--;
}
inline int ask(int l,int r)
{
    int ans=0;
    if(bel[l]==bel[r])
    {
        for(int i=l;i<=r;i++)
        {
            if(cnt[i])ans++;
        }
        return ans;
    }
    for(int i=l;i<=bel[l]*divi;i++)
    {
        if(cnt[i])
        {
            ans++;
        }
    }
    for(int i=((bel[r]-1)*divi)+1;i<=r;i++)
    {
        if(cnt[i])
        {
            ans++;
        }
    }
    for(int i=bel[l]+1;i<bel[r];i++)
    {
        ans+=val[i];
    }
    return ans;
}
int main()
{
    int l=1,r=0;
    n=init();m=init();
    block=sqrt(m);
    divi=sqrt(n);
    for(int i=1;i<=n;i++)
    {
        a[i]=init();
        bel[i]=((i-1)/divi)+1;
    }
    for(int i=1;i<=m;i++)
    {
        query[i].l=init();query[i].r=init();query[i].a=init();query[i].b=init();
        query[i].id=i;
    }
    sort(query+1,query+1+m,cmp);
    for(int i=1;i<=m;i++)
    {
        if(query[i].r>r)
        {
            for(r=r+1;r<=query[i].r;r++)
            {
                Plus(r);
            }
        }
        else if(query[i].r<r)
        {
            for(;r>query[i].r;r--)
            {
                Minus(r);
            }
        }
        if(query[i].l>l)
        {
            for(;l<query[i].l;l++)
            {
                Minus(l);
            }
        }
        else if(query[i].l<l)
        {
            for(l=l-1;l>=query[i].l;l--)
            {
                Plus(l);
            }
        }
        l=query[i].l;r=query[i].r;
        query[i].ans=ask(query[i].a,query[i].b);
    }
    sort(query+1,query+1+m,cmpid);
    for(int i=1;i<=m;i++)
    {
        printf("%d\n",query[i].ans);
    }
    return 0;
}
/*
srO xudyh davidlee1999WTK linkct1999 Orz
compiler TDM-GCC 5.9.2
*/
View Code

 

posted @ 2017-03-04 17:15  redwind  阅读(316)  评论(0编辑  收藏  举报