loj #6201. 「YNOI2016」掉進兔子洞

#6201. 「YNOI2016」掉進兔子洞

您正在打galgame,而後忽然發現您今天太頹了,因而想寫個數據結構題練練手:html

給出一個長爲 nnn 的序列 aaa。node

有 mmm 個詢問,每次詢問三個區間,把三個區間中同時出現的數一個一個刪掉,問最後三個區間剩下的數的個數和,詢問獨立。ios

注意這裏刪掉指的是一個一個刪,不是把等於這個值的數直接刪完,好比三個區間是 [1,2,2,3,3,3,3][1,2,2,3,3,3,3][1,2,2,3,3,3,3] , [1,2,2,3,3,3,3][1,2,2,3,3,3,3][1,2,2,3,3,3,3] 與 [1,1,2,3,3][1,1,2,3,3][1,1,2,3,3],就一塊兒扔掉了 111 個 111,111 個 222,222 個 333。數據結構

輸入格式

第一行兩個數表示 nnn , mmm。ui

第二行 nnn個數表示 aia_iai​​。spa

以後 mmm 行,每行 666 個數 l1l_1l1​​ , r1r_1r1​​ , l2l_2l2​​ , r2r_2r2​​ , l3l_3l3​​ , r3r_3r3​​ 表示這三個區間。code

輸出格式

對於每一個詢問,輸出一個數表示答案。htm

樣例

SAMPLE INPUT

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

SAMPLE OUTPUT

3
0

數據範圍與提示

1≤n,m≤1051 \leq n,m \leq 10^{5}1n,m105​​ , 1≤ai≤1091 \leq a_i \leq 10^{9}1ai​​109​​blog

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<bitset>
#include<cmath>
#define maxn 100010
using namespace std;
int n,a[maxn],b[maxn],cnt[maxn],pos[maxn],block,tot,ans[maxn],T=25000;
bool mark[maxn];
struct node{int l,r,id;}q[maxn];
bitset<100000>F[25001],f;
bool cmp(node a,node b){
    if(pos[a.l]==pos[b.l])return a.r<b.r;
    return pos[a.l]<pos[b.l];
}
void update(int k,int ty){
    k=a[k];cnt[k]+=ty;
    if(ty==1)f[k+cnt[k]-2]=1;
    else f[k+cnt[k]-1]=0;
}
void solve(int m){
    int L,R,l1,l2,l3,r1,r2,r3;
    memset(cnt,0,sizeof(cnt));
    memset(mark,0,sizeof(mark));
    f.reset();tot=0;
    for(int i=1;i<=m;i++){
        scanf("%d%d%d%d%d%d",&l1,&r1,&l2,&r2,&l3,&r3);
        q[++tot]=(node){l1,r1,i};
        q[++tot]=(node){l2,r2,i};
        q[++tot]=(node){l3,r3,i};
        ans[i]=r3+r2+r1-l3-l2-l1+3;
    }
    sort(q+1,q+tot+1,cmp);
    L=1;R=0;
    for(int i=1;i<=tot;i++){
        while(R<q[i].r)update(++R,1);
        while(R>q[i].r)update(R--,-1);
        while(L<q[i].l)update(L++,-1);
        while(L>q[i].l)update(--L,1);
        if(mark[q[i].id])F[q[i].id]&=f;
        else F[q[i].id]=f,mark[q[i].id]=1;
    }
    for(int i=1;i<=m;i++){
        int k=F[i].count();
        printf("%d\n",ans[i]-3*k);
    }
}
int main(){
    int m;
    scanf("%d%d",&n,&m);
    block=sqrt(n);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        b[i]=a[i];
        pos[i]=(i-1)/block+1;
    }
    sort(b+1,b+n+1);
    for(int i=1;i<=n;i++)
        a[i]=lower_bound(b+1,b+n+1,a[i])-b;
    while(m){
        if(m<=T)solve(m),m=0;
        else solve(T),m-=T;
    }
    return 0;
}
相關文章
相關標籤/搜索