BZOJ3207:花神的嘲讽计划

浅谈主席树:https://www.cnblogs.com/AKMer/p/9956734.html

题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=3207

\(k\)\(hash\)一下,然后直接找区间内有没有\(hash\)值。

时间复杂度:\(O(mlogn)\)

空间复杂度:\(O(nlogn)\)

代码如下:

#include <map>
#include <cstdio>
using namespace std;

const int maxn=1e5+5,base=2333;

map<int,int>s;
int n,m,k,bin=1,id;
int rt[maxn],p[maxn],a[maxn];

int read() {
    int x=0,f=1;char ch=getchar();
    for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
    for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
    return x*f;
}

struct tree_node {
    int cnt,ls,rs;
};

struct chairman_tree{
    int tot;
    tree_node tree[maxn*18];

    void ins(int lst,int &now,int l,int r,int pos) {
        now=++tot;tree[now]=tree[lst];
        tree[now].cnt++;
        if(l==r)return;
        int mid=(l+r)>>1;
        if(pos<=mid)ins(tree[lst].ls,tree[now].ls,l,mid,pos);
        else ins(tree[lst].rs,tree[now].rs,mid+1,r,pos);
    }

    bool query(int lst,int now,int l,int r,int pos) {
        if(l==r)return tree[now].cnt-tree[lst].cnt>0;
        int mid=(l+r)>>1;
        if(pos<=mid)return query(tree[lst].ls,tree[now].ls,l,mid,pos);
        return query(tree[lst].rs,tree[now].rs,mid+1,r,pos);
    }
}T;

int main() {
    n=read(),m=read(),k=read();
    for(int i=1;i<=k;i++)bin*=base;
    for(int i=1;i<=n;i++) {
        int x=read();
        p[i]=p[i-1]*base+x;
    }
    for(int i=1;i<=n-k+1;i++) {
        int tmp=p[i+k-1]-p[i-1]*bin;
        if(!s[tmp])s[tmp]=++id;
        a[i]=s[tmp];
    }
    for(int i=1;i<=n;i++)
        T.ins(rt[i-1],rt[i],1,id,a[i]);
    for(int i=1;i<=m;i++) {
        int x=read(),y=read(),tmp=0;
        for(int j=1;j<=k;j++) {
            int v=read();
            tmp=tmp*base+v;
        }
        if(y-x+1<k||s[tmp]==0)puts("Yes");
        else if(T.query(rt[x-1],rt[y-k+1],1,id,s[tmp]))puts("No");
        else puts("Yes");
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/AKMer/p/9974597.html