P4396 [AHOI2013]作業 (莫隊+分塊)

題目描述

此時己是凌晨兩點,剛剛做了Codeforces的小A掏出了英語試卷。英語作業其實不算多,一個小時剛好可以做完。然後是一個小時可以做完的數學作業,接下來是分別都是一個小時可以做完的化學,物理,語文......小A壓力巨大。

這是小A碰見了一道非常噁心的數學題,給定了一個長度爲n的數列和若干個詢問,每個詢問是關於數列的區間表示數列的第l個數到第r個數),首先你要統計該區間內大於等於a,小於等於b的數的個數,其次是所有大於等於a,小於等於b的,且在該區間中出現過的數值的個數。

小A望着那數萬的數據規模幾乎絕望,只能向大神您求救,請您幫幫他吧。

輸入輸出格式

輸入格式:

 

第一行n,m

接下來n個數表示數列

接下來m行,每行四個數l,r,a,b

 

輸出格式:

 

輸出m行,分別對應每個詢問,輸出兩個數,分別爲在l到r這段區間中大小在[a,b]中的數的個數,以及大於等於a,小於等於b的,且在該區間中出現過的數值的個數(具體可以參考樣例)。

 

輸入輸出樣例

輸入樣例#1: 複製

3 4
1 2 2
1 2 1 3
1 2 1 1
1 3 1 3
2 3 2 3

輸出樣例#1: 複製

2 2
1 1
3 2
2 1

說明

N<=100000,M<=100000

解題思路:本來是學習線段樹在分治上的應用找的練習題,結果跑偏了。。

這個與項鍊的那個題很像,區間不同數的個數有很多種實現方式。。這個多了一個限制條件就是要求在a,b範圍內

這個其實也好辦,直接分塊。。。。

統計塊內數字的個數,和不同數的個數,對於不是完整的塊的話直接暴力。。。

#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<set>
#include<cmath>
#include<map>
#include<algorithm>
#include<cstring>
using namespace std;
#define rep(i,j,k) for(int i=j;i<=k;i++)
#define sca(x) scanf("%d",&x)
#define pb(x) push_back(x)
#define per(i,j,k) for(int i=j;i>=k;i--)
#define inf 0x3f3f3f3f
#define LL long long
#define N 200005
#define MAXN 100000
#define inf 0x3f3f3f3f

int B[N],A[N];
struct node
{
    int ql,qr,a,b,id;
    bool friend operator <(node x,node y)
    {
        if(B[x.ql]!=B[y.ql])return B[x.ql]<B[y.ql];
        else return x.qr<y.qr;
    }

}Q[N];

struct node1
{
    int a1,a2;
}ou[N];

int len;
int C[N],D[N],E[N];

void add(int x)
{
    ++C[x];
    ++D[B[x]];
    if(C[x]==1)++E[B[x]];
}

void del(int x)
{
    --C[x];
    --D[B[x]];
    if(C[x]==0)--E[B[x]];
}

void query(int a,int b,int k)
{
    for(int i=a;i<=min(b,B[a]*len);i++)
    {
        if(C[i])ou[k].a1+=C[i],ou[k].a2++;
    }
    if(B[a]!=B[b])
    {
        for(int i=(B[b]-1)*len+1;i<=b;i++)
        {
            if(C[i])ou[k].a1+=C[i],ou[k].a2++;
        }
    }
    rep(i,B[a]+1,B[b]-1)
    {
        ou[k].a1+=D[i];
        ou[k].a2+=E[i];
    }
}
void solve(int n,int m)
{
    int r=0,l=1;
    rep(i,1,m)
    {
        while(r<Q[i].qr)add(A[++r]);
        while(r>Q[i].qr)del(A[r--]);
        while(l>Q[i].ql)add(A[--l]);
        while(l<Q[i].ql)del(A[l++]);
        query(Q[i].a,Q[i].b,Q[i].id);
    }
    rep(i,1,m)
    {
        printf("%d %d\n",ou[i].a1,ou[i].a2);
    }
}
int main()
{
    int n,m;
    sca(n),sca(m);
    len=sqrt(n);
    rep(i,1,n)sca(A[i]);
    rep(i,1,n)B[i]=(i-1)/len+1;
    rep(i,1,m)
    {
        scanf("%d%d%d%d",&Q[i].ql,&Q[i].qr,&Q[i].a,&Q[i].b);
        Q[i].id=i;
    }
    sort(Q+1,Q+1+m);
    solve(n,m);
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章