CDQZ Challenge 16

说在前面:“CDQZ”系列题目数据绝对良心(良苦用心233),提交网址如有需要请私信本蒟蒻。
1016:Challenge 16
查看 提交 统计 提问
总时间限制: 80000ms 单个测试点时间限制: 10000ms 内存限制: 512000kB
描述
给你一个长度为n的数列a和m次询问。

每次询问给定四个数l, r, x, y,表示询问在a[l .. r]中,对于所有x ≤ a[i] ≤ y的数,它们的个数以及它们中所有不同的数的个数。

输入
第一行两个数n, m。
第二行n个整数ai。
接下来m行每行一个询问l, r, x, y。
输出
输出m行,每行两个整数表示询问的两个答案。
样例输入
3 4
1 2 2
1 2 1 3
1 2 1 1
1 3 1 3
2 3 2 3
样例输出
2 2
1 1
3 2
2 1
提示
1 ≤ n, m ≤ 100,000,输入数据在int范围内
来源
hejiaao

题解:离散化,莫队+值域分块(同bzoj 3236)

#include
#include
#include
#include
#include
#include
using namespace std;
#define pii pair
#define mp(x,y) make_pair(x,y)
const int MAXN=1e5+2;
int n,m,siz,a[MAXN],b[MAXN*3],tt=0;
int bel[MAXN],cnt[MAXN],num[MAXN],blo[MAXN];
pii ans[MAXN];
inline int read() {
    int x=0,f=1;char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    return x*f;
}
struct Q {
    int l,r,a,b,id;
    friend bool operator <(const Q &x,const Q &y) {
        return bel[x.l]^bel[y.l]?bel[x.l]y.l]:x.r<y.r;
    }
}q[MAXN];
inline void update(int pos,int delta) {
    int temp=a[pos];
    cnt[temp]+=delta,num[bel[temp]]+=delta;
    if (delta==-1&&!cnt[temp]) --blo[bel[temp]];
    if (delta==1&&cnt[temp]==1) ++blo[bel[temp]];
}
pii query(int st,int ed) {
    int fi=0,se=0;
    if (bel[st]==bel[ed]) {//in the same block
        for (int i=st;i<=ed;++i)
            if (cnt[i]) fi+=cnt[i],++se;
    }
    else {//across a few blocks
        for (int i=st;i<=bel[st]*siz;++i)
            if (cnt[i]) fi+=cnt[i],++se;
        for (int i=(bel[ed]-1)*siz+1;i<=ed;++i)
            if (cnt[i]) fi+=cnt[i],++se;
        for (int i=bel[st]+1;iif (num[i]) fi+=num[i],se+=blo[i];
    }
    return mp(fi,se);
}
int main() {
//  freopen("Challenge 16.in","r",stdin);
    n=read(),m=read(),siz=(int)sqrt((double)n);
    for (register int i=1;i<=n;++i) b[++tt]=a[i]=read(),bel[i]=(i-1)/siz+1;
    for (register int i=1;i<=m;++i) q[i].l=read(),q[i].r=read(),b[++tt]=q[i].a=read(),b[++tt]=q[i].b=read(),q[i].id=i;
    sort(b+1,b+tt+1);
    int nn=unique(b+1,b+tt+1)-b-1;
    for (register int i=1;i<=n;++i) a[i]=lower_bound(b+1,b+nn+1,a[i])-b;
    for (register int i=1;i<=m;++i) q[i].a=lower_bound(b+1,b+nn+1,q[i].a)-b,q[i].b=lower_bound(b+1,b+nn+1,q[i].b)-b;
    sort(q+1,q+m+1);
    for (register int i=1,l=1,r=0;i<=m;++i) {
        while (l<q[i].l) update(l++,-1);
        while (r>q[i].r) update(r--,-1);
        while (l>q[i].l) update(--l,1);
        while (r<q[i].r) update(++r,1);
        ans[q[i].id]=query(q[i].a,q[i].b);
    }
    for (register int i=1;i<=m;++i) printf("%d %d\n",ans[i].first,ans[i].second);
    return 0;
}

你可能感兴趣的:(OI-数据结构)