• BZOJ 3207 花神的嘲讽计划I (hash)


    题意

    1e5的数组,1e5的询问,每次给你的长度相同(<=20)的一组数,和(l,r),问你这组数是不是(l,r)内的子串

    思路

    思路还是蛮好想的..
    hash出(i,i+k-1)的子串,然后每次在主席树内查询,但是不知道为什么一直wa..自己造了很多组数据都没抛出错误..(找到错误了是hash模数太蠢)
    网上看到stl过的,发现自己撒比了
    先将数组里hash值一样的扔到set里,每次只需要将询问串的hash在set里lower_bound(l),判断它存在并且<=r-k+1即可

    似乎可以总结一下:判断某区间是否存在一个值,set里二分就行?

    代码

    值域里二分:

    int t;
    int n,m,k;
    ll a[maxn];
    ull pre[maxn];
    ull po[maxn];
    ll gt(int l, int r){
        return (pre[r]-pre[l-1]*po[r-l+1]);
    }
    vector<ll>v;
    int getid(ll x){
        return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
    }
    set<int>s[maxn];
    int main() {
        po[0]=1;
        scanf("%d %d %d", &n, &m, &k);
        for(int i = 1; i <= n; i++)po[i]=po[i-1]*1337;
        for(int i = 1; i <= n; i++){
            scanf("%lld", &a[i]);
            pre[i]=pre[i-1]*1337+a[i];
        }
        for(int i = 1; i+k-1<=n; i++){
            v.pb(gt(i,i+k-1));
        }
        sort(v.begin(),v.end());
        v.erase(unique(v.begin(),v.end()),v.end());
        int ntot = v.size();
        for(int i = 1; i+k-1<=n; i++){
            a[i]=getid(gt(i,i+k-1));
            s[a[i]].insert(i);
        }
        while(m--){
            int x,y;
            ll tmp = 0;
            scanf("%d %d", &x, &y);
            for(int i = 1; i <= k; i++){
                int o;
                scanf("%d", &o);
                tmp=tmp*1337+o;
            }
            int id = getid(tmp);
            if(v[id-1]!=tmp){
                printf("Yes
    ");
                continue;
            }
            set<int>::iterator it = s[id].lower_bound(x);
            if(it!=s[id].end()&&*it<=y-k+1)printf("No
    ");
            else printf("Yes
    ");
    
        }
    
        return 0;
    }
    

    主席树:

    int t;
    int n,m,k;
    ll a[maxn];
    ull pre[maxn];
    ull po[maxn];
    ull gt(int l, int r){
        return (pre[r]-pre[l-1]*po[r-l+1]);
    }
    vector<ull>v;
    int getid(ull x){
        return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
    }
    int ls[40*maxn],rs[40*maxn];
    ll dat[40*maxn];
    int root[maxn];
    int tot;
    int insert(int now, int l, int r, int x, int val){
        int p = ++tot;
        ls[p]=ls[now];rs[p]=rs[now];dat[p]=dat[now];
        if(l==r){
            dat[p]=1;return p;
        }
        int mid = l+r>>1;
        if(x<=mid)ls[p]=insert(ls[now],l,mid,x,val);
        else rs[p]=insert(rs[now],mid+1,r,x,val);
        dat[p]=dat[ls[p]]+dat[rs[p]];
        return p;
    }
    int ck(int x, int y, int l, int r, int k){
        int mid =l+r>>1;
        if(l==r)return dat[y]-dat[x];
        if(k<=mid){
            return ck(ls[x],ls[y],l,mid,k);
        }
        else return ck(rs[x],rs[y],mid+1,r,k);
    
    }
    
    int main() {
        //freopen("wrjAc.in","r",stdin);
        //freopen("wrjMy.out","w",stdout);
        scanf("%d %d %d", &n, &m, &k);
        po[0]=1;
        for(int i = 1; i <= n; i++)po[i]=po[i-1]*1337;
        for(int i = 1; i <= n; i++){
            scanf("%lld", &a[i]);
            pre[i]=pre[i-1]*1337+a[i];
        }
        for(int i = 1; i+k-1<=n; i++){
            v.pb(gt(i,i+k-1));
        }
        sort(v.begin(),v.end());
        v.erase(unique(v.begin(),v.end()),v.end());
        int ntot = v.size();
        for(int i = 1; i+k-1<=n; i++){
            a[i]=getid(gt(i,i+k-1));
            root[i]=insert(root[i-1],1,ntot,a[i],1);
        }
        while(m--){
            int x,y;
            ull tmp = 0;
            scanf("%d %d", &x, &y);
            for(int i = 1; i <= k; i++){
                int o;
                scanf("%d", &o);
                tmp=tmp*1337+o;
            }
            int id = getid(tmp);
            if(v[id-1]!=tmp){
                printf("Yes
    ");
                continue;
            }
    
            int ans = ck(root[x-1],root[y-k+1],1,ntot,id);
            if(ans>0)printf("No
    ");
            else printf("Yes
    ");
    
        }
        return 0;
    }
    
  • 相关阅读:
    Leetcode 130. 被围绕的区域(中等)DFS||并查集
    Leetcode 207. 课程表 && 210. 课程表 II
    Leetcode 355. 设计推特(中等) 多路归并&面向对象设计
    Leetcode 277.搜索名人(中等) 图相关名流问题
    Leetcode 785. 判断二分图(中等)& 886. 可能的二分法(中等) 二分图判断
    Leetcode 295. 数据流的中位数(困难)
    Leetcode 990. 等式方程的可满足性(中等) 并查集
    Leetcode 743. 网络延迟时间(中等) 1514. 概率最大的路径(中等) 1631. 最小体力消耗路径(中等)Dijkstra求两点间的最小权重和
    Leetcode 261. 以图判树(中等) 1135. 最低成本联通所有城市(中等) 1584. 连接所有点的最小费用(中等) 并查集&Kruskal最小生成树
    java创建线程池
  • 原文地址:https://www.cnblogs.com/wrjlinkkkkkk/p/12596096.html
Copyright © 2020-2023  润新知