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

#6201. 「YNOI2016」掉进兔子洞

您正在打galgame,然后突然发现您今天太颓了,于是想写个数据结构题练练手:

给出一个长为 nnn 的序列 aaa。

有 mmm 个询问,每次询问三个区间,把三个区间中同时出现的数一个一个删掉,问最后三个区间剩下的数的个数和,询问独立。

注意这里删掉指的是一个一个删,不是把等于这个值的数直接删完,比如三个区间是 [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。

第二行 nnn个数表示 aia_iai​​。

之后 mmm 行,每行 666 个数 l1l_1l1​​ , r1r_1r1​​ , l2l_2l2​​ , r2r_2r2​​ , l3l_3l3​​ , r3r_3r3​​ 表示这三个区间。

输出格式

对于每个询问,输出一个数表示答案。

样例

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​​

#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;
}

 

posted @ 2018-05-03 19:11  Echo宝贝儿  阅读(418)  评论(0编辑  收藏  举报