zoukankan      html  css  js  c++  java
  • 牛客多校第3场 J 思维+树状数组+二分

    牛客多校第3场 J 思维+树状数组+二分

    传送门:https://ac.nowcoder.com/acm/contest/883/J

    题意:

    给你q个询问,和一个队列容量f

    询问有两种操作:

    0.访问操作,如果询问的name在队列中存在的话,那么就输出队列中name对应的val值,然后将队列中name对应的元素扔到队列的尾部去,否则就直接将该元素插入到队列的尾部去

    1.插入操作,得到队列中对应的name元素的v值为k,查询第k+v个元素的v值是多少

    题解:

    已知,对于插入操作,我们需要很快的查询对应的name值的val

    所以我们考虑map映射,为了解决string过慢的问题,我们将stringhash成一个unsigned long long的值

    我们记录有多少个数被插入了,还有每个点的绝对坐标,如果在0操作中 点x被丢弃了,那么我们就对x位置打上标记1,这样,在我们查询第y个操作时,实际上,这个y操作对于的位置就是 查询这个y对应的pos位减去当前位置之前被删掉的数的和加上 v值

    我们用tot统计被插入数的数量,因为一开始就是空串,所以tot实际上就代表队列中有多少个数,如果tot>m,我们就丢弃队头的元素

    对于每次查询,我们是找当前位置向左的位置,因为我们删除的数实际上只是给打上了一个+1的标记,所以我们需要找到左边真正存在的那个数,这个右端点不太好找,所以我们考虑二分,二分当前位置是否是第r个点

    check就直接用二分出来的mid减去mid之前的丢弃的个数,如果这个个数>当前个数,那么就改变二分的上界r,否则改变二分的下界l

    然后就可以得到满足真正的pos+1的位置的值的数了

    emmm复杂度应该是两个log 被卡map的操作然后有迭代器 实现mp的操作,这样卡过去了 600+ms 海星吧

    代码:

    #include <set>
    #include <map>
    #include <stack>
    #include <cmath>
    #include <queue>
    #include <cstdio>
    #include <string>
    #include <vector>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <unordered_map>
    #include <assert.h>
    
    using namespace std;
    typedef long long LL;
    typedef pair<int, int> pii;
    typedef unsigned long long uLL;
    #define ls rt<<1
    #define rs rt<<1|1
    #define lson l,mid,rt<<1
    #define rson mid+1,r,rt<<1|1
    #define bug printf("*********
    ")
    #define FIN freopen("input.txt","r",stdin);
    #define FON freopen("output.txt","w+",stdout);
    #define IO ios::sync_with_stdio(false),cin.tie(0)
    #define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]
    "
    #define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]
    "
    #define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]
    "
    const int maxn = 5e5 + 5;
    const int INF = 0x3f3f3f3f;
    const int mod = 1e9 + 7;
    const double Pi = acos(-1);
    const int seed = 1331;
    LL quick_pow(LL x, LL y) {
        LL ans = 1;
        while(y) {
            if(y & 1) {
                ans = ans * x % mod;
            } x = x * x % mod;
            y >>= 1;
        } return ans;
    }
    int lowbit(int x) {
        return x & (-x);
    }
    int bit[maxn];
    void add(int pos, int val) {
        while(pos < maxn) {
            bit[pos] += val;
            pos += lowbit(pos);
        }
    }
    int query(int pos) {
        int res = 0;
        while(pos) {
            res += bit[pos];
            pos -= lowbit(pos);
        }
        return res;
    }
    void clear(int pos, int MM) {
        while(pos < MM) {
            bit[pos] = 0;
            pos += lowbit(pos);
        }
    }
    uLL Hash(char *x) {
        uLL h = 0;
        for(int i = 0; x[i]; i++) {
            h = h * seed + x[i];
        }
        return h;
    }
    int op;
    int v;
    int val[maxn];
    uLL hname[maxn];
    char name[20];
    map<uLL, int> mp;
    int get_pos(int p, int tot) { //虽然名字是tot,但是要传入index
        int pos = -1;
        int l = 1, r = tot;
        while(r >= l) {
            int mid = (l + r) / 2;
            int num =  mid - query(mid);
            if(num >= p) {
                r = mid - 1;
                pos = mid;
            } else {
                l = mid + 1;
            }
        }
        assert(pos != -1);
        return pos;
    }
    
    map<uLL, int>:: iterator iter;
    int main() {
    
        int T;
        scanf("%d", &T);
        while(T--) {
    
            mp.clear();
            int m, k;
            scanf("%d%d", &k, &m);
            memset(bit, 0, sizeof(bit));
            int Index = 0;
            int tot = 0;
            for(int i = 1; i <= k; i++) {
                scanf("%d%s%d", &op, name, &v);
                uLL h = Hash(name);
                iter = mp.find(h);
                if(op == 0) {
                    if(iter != mp.end()) {
                        int pos = iter->second;
                        printf("%d
    ", val[pos]);
                        add(pos, 1);
                        Index++;//charu
                        hname[Index] = h;
                        val[Index] = val[pos];
                        iter->second = Index;
                    } else {
                        printf("%d
    ", v);
                        tot++;
                        if(tot > m) {
                            tot--;
                            int pos = get_pos(1, Index);
                            add(pos, 1);
                            iter = mp.find(hname[pos]);
                            if(iter != mp.end())mp.erase(iter);
                        }
                        Index++;
                        mp[h] = Index;
                        hname[Index] = h;
                        val[Index] = v;
                    }
                } else {
                    if(iter == mp.end()) {
                        printf("Invalid
    ");
                        continue;
                    }
                    int vv = iter->second;
                    int pos = vv - query(vv - 1);
                    pos += v;
                    if(pos > tot || pos < 1) {
                        printf("Invalid
    ");
                    } else {
                        pos = get_pos(pos, Index);
                        printf("%d
    ", val[pos]);
                    }
                }
            }
        }
        return 0;
    }
    
  • 相关阅读:
    Lucene基础排序算法改进
    大数据量的过滤 (用于爬虫,蜘蛛) Bloom Filter 布隆过滤器
    往空间,博客里添加音乐播放器
    汇编随笔
    一个女程序员的故事(酷壳陈皓)
    cmd 命令之删除整个文件夹
    亿度空间
    用wubi.exe安装ubuntu下载速度很慢怎么办?
    qtm第一次
    copy的妙用
  • 原文地址:https://www.cnblogs.com/buerdepepeqi/p/11246824.html
Copyright © 2011-2022 走看看