P4688 [Ynoi2016]掉进兔子洞

//Pro:P4688 [Ynoi2016]掉进兔子洞

//ans= r1-l1+1 + r2-l2+1 +r3-l3+1 - ∑min(cnt1[i],cnt2[i],cnt3[i])*3
//计算cnt可以用莫队

//如何计算cnt的min
//用bitset (第一次用这玩意真神奇
//将原数组排个序 
//将每个数离散化为它在有序数组中出现的第一个位置
//bitset里的每一位对应有序后的原数组的每一位 
//那么对于一个询问,三个bitset的&就是∑min(cnt1[i],cnt2[i],cnt3[i])  

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<bitset>
using namespace std;

typedef long long LL;

inline int read()
{
    char c=getchar();int num=0;
    for(;!isdigit(c);c=getchar());
    for(;isdigit(c);c=getchar())
        num=num*10+c-'0';
    return num;
}

const int N=100000;
const int T=25000;

int n,m,bound;
int a[N+5],b[N+5];
int belong[N+5];
struct LINE
{
    int l,r,id;
    bool operator < (const LINE &A) const
    {
        return belong[l]==belong[A.l]?r<A.r:l<A.l;
    }
}line[T*3+5];
bitset<N> F[T+5],f;

int ans[T+5],cnt[N+5];
bool mark[T+5];

inline void update(int pos,bool flag)
{
    int x=a[pos];
    if(flag)
        ++cnt[x],f[x+cnt[x]-2]=1;
    else
        f[x+cnt[x]-2]=0,--cnt[x];
}

inline void solve(int t)
{
    bound=0;
    memset(mark,0,sizeof(mark));
    memset(ans,0,sizeof(ans));
    for(int i=1;i<=t;++i)
    {
        for(int j=0;j<3;++j)
        {
            line[++bound].l=read(),
            line[bound].r=read(),
            line[bound].id=i;
            ans[i]+=line[bound].r-line[bound].l+1;
        }
    }
    sort(line+1,line+bound+1);
    f.reset();
    memset(cnt,0,sizeof(cnt));
    int L=1,R=0;
    for(int i=1;i<=bound;++i)
    {
        for(;R<line[i].r;update(++R,1));
        for(;L>line[i].l;update(--L,1));
        for(;R>line[i].r;update(R--,0));
        for(;L<line[i].l;update(L++,0));
        if(!mark[line[i].id])
            F[line[i].id]=f,mark[line[i].id]=1;
        else
            F[line[i].id]&=f;
    }
    for(int i=1;i<=t;++i)
    {
        ans[i]-=F[i].count()*3;
        cout<<ans[i]<<'\n';
    }
}

int S;
int main()
{
    n=read(),m=read();
    S=sqrt(n);
    for(int i=1;i<=n;++i)
    {
        b[i]=read(),a[i]=b[i];
        belong[i]=(i-1)/S+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-09-12 11:06  whymhe  阅读(244)  评论(0编辑  收藏  举报