JZOJ2939统计

题目大意及模型转换

给定N个数(N<=10^5),现在有M(M<=10^5)个询问,每个询问形如区间L..R是否存在X。

主席树

显然离散化后用主席树。
这就是我看完题目后的第一想法。
但是,我们有更短的做法。

在线大法

我们根据数值为第一关键字位置为第二关键字排序。
那么每个询问我们只需要二分出位置>=L中最小的数值为X的位置。
然后检验是否<=R。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define maxn (100000+5)
using namespace std;
struct dong{
    int data,id;
} a[maxn];
int i,j,k,l,r,mid,x,y,t,n,m,ans;
int read(){
    int x=0,f=1;
    char ch=getchar();
    while (ch<'0'||ch>'9'){
        if (ch=='-') f=-1;
        ch=getchar();
    }
    while (ch>='0'&&ch<='9'){
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x*f;
}
bool cmp(dong a,dong b){
    if (a.data<b.data) return 1;
    else if (a.data==b.data&&a.id<b.id) return 1;
    else return 0;
}
int main(){
    n=read();
    fo(i,1,n){
        a[i].id=i;a[i].data=read();
    }
    sort(a+1,a+n+1,cmp);
    m=read();
    fo(i,1,m){
        x=read();y=read();t=read();
        ans=0;
        l=1;r=n;
        while (l<=r){
            mid=(l+r)/2;
            if (a[mid].data>t) r=mid-1;
            else if (a[mid].data<t) l=mid+1;
            else if (a[mid].data==t&&a[mid].id<x) l=mid+1;
            else{
                ans=mid;
                r=mid-1;
            }
        }
        if (ans){
            if (a[ans].data==t&&a[ans].id>=x&&a[ans].id<=y) printf("1");else printf("0");
        }
        else printf("0");
    }
}

你可能感兴趣的:(JZOJ2939统计)