BZOJ 3809 Gty的二逼妹子序列

Posted on 2017-02-23 17:03  ziliuziliu  阅读(142)  评论(0编辑  收藏  举报

暴力。。。严格的说是mlogn+m√nlogn的。。。就是莫队+BIT。

然后我们可以按照值域分块,这样修改O(1)查询O(√n),这样总复杂度就是2*m*√n。

有点像做了一个时间复杂度的权衡。。。看起来查询变慢了,事实上总复杂度是变快了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 100050
#define maxm 1000050
using namespace std;
int n,m,len=300,blo[maxn],st[maxn],ret=0,val[maxn],cnt[maxn],a[maxn],ans[maxm],p1,p2;
int a1,a2,a3,a4;
struct query
{
    int l,r,a,b,id;
    query (int l,int r,int a,int b,int id):l(l),r(r),a(a),b(b),id(id) {}
    query () {}
}q[maxm];
int read()
{
    char ch;int data=0;
    while (ch<'0' || ch>'9') ch=getchar();
    while (ch>='0' && ch<='9')
    {
        data=data*10+ch-'0';
        ch=getchar();
    }
    return data;
}
bool cmp(query x,query y)
{
    if (blo[x.l]==blo[y.l]) return x.r<y.r;
    return blo[x.l]<blo[y.l];
}
void build()
{
    ret=1;
    for (int i=1;i<=n;i++)
    {
        blo[i]=ret;
        if (!(i%len)) {st[ret]=i;if (i!=n) ret++;}
    }
    if (n%len) st[ret]=n;
}
void modify(int x,int y)
{
    bool flag=cnt[x];
    cnt[x]+=y;
    if ((!cnt[x]) && (flag)) val[blo[x]]--;
    if ((cnt[x]) && (!flag)) val[blo[x]]++;
}
int ask(int l,int r)
{
    int ret1=0,ret2=0;
    for (int i=1;i<=blo[l-1]-1;i++) ret1+=val[i];
    for (int i=st[blo[l-1]-1]+1;i<=l-1;i++) ret1+=(cnt[i]>0);
    for (int i=1;i<=blo[r]-1;i++) ret2+=val[i];
    for (int i=st[blo[r]-1]+1;i<=r;i++) ret2+=(cnt[i]>0);
    return ret2-ret1;
}
int main()
{
    n=read();m=read();
    for (int i=1;i<=n;i++) a[i]=read();
    for (int i=1;i<=m;i++)
    {
        scanf("%d%d%d%d",&a1,&a2,&a3,&a4);
        q[i]=query(a1,a2,a3,a4,i);
    }
    build();
    sort(q+1,q+m+1,cmp);
    for (int i=1;i<=m;i++)
    {
        for (;p1>q[i].l;p1--) modify(a[p1-1],1);
        for (;p1<q[i].l;p1++) modify(a[p1],-1);
        for (;p2>q[i].r;p2--) modify(a[p2],-1);
        for (;p2<q[i].r;p2++) modify(a[p2+1],1);
        ans[q[i].id]=ask(q[i].a,q[i].b);
    }
    for (int i=1;i<=m;i++) printf("%d\n",ans[i]);
    return 0;
}