• 2018牛客多校第四场 J.Hash Function


    题意:

      给出一个已知的哈希表。求字典序最小的插入序列,哈希表不合法则输出-1。

    题解:

      对于哈希表的每一个不为-1的数,假如他的位置是t,令s = a[t]%n。则这个数可以被插入当且仅当第s ~ t-1个数都不为-1且已经插入完成。

      那么对于每一个这样的数,需要连t-s条边(s<=t)或者t+n-s条边(s>t)。

      总的边数有O(n^2)条。可以用线段树优化建图。最后跑一边拓扑排序。

      对于不合法的情况,第s ~ t-1个数存在-1或者拓扑图存在环会导致不合法。

    #include <bits/stdc++.h>
    using namespace std;
    #define P pair<int, int>
    const int N = 4e5+10;
    int t, n;
    int cnt, tot;
    int ans[N];
    int a[N], pre[N];
    int pos[N], rt[N<<2], deg[N<<2];
    int head[N<<3], nxt[N<<3], to[N<<3];
    priority_queue<P, vector<P>, greater<P> > q;
    void add_edge(int u, int v) {
        to[++tot] = v;
        nxt[tot] = head[u];
        head[u] = tot;
        deg[v]++;
    }
    void build(int id, int l, int r) {
        rt[id] = -1;
        if(l == r) {
            pos[l] = id;
            rt[id] = l;
            return;
        }
        int mid = l+r>>1;
        build(id<<1, l, mid);
        build(id<<1|1, mid+1, r);
        add_edge(id<<1, id);
        add_edge(id<<1|1, id);
    }
    void update(int id, int l, int r, int ql, int qr, int v) {
        if(ql <= l && r <= qr) {
            add_edge(id, v);
            return ;
        }
        int mid = l+r>>1;
        if(ql <= mid) update(id<<1, l, mid, ql, qr, v);
        if(qr > mid) update(id<<1|1, mid+1, r, ql, qr, v);
    }
    int main() {
        scanf("%d", &t);
        while(t--) {
            tot = 0;
            scanf("%d", &n);
            memset(head, -1, sizeof(int)*(n<<3));
            memset(deg, 0, sizeof(int)*(n<<2));
            for(int i = 0; i < n; i++) {
                scanf("%d", &a[i]);
                pre[i] = a[i] == -1;
                if(i) pre[i] += pre[i-1];
            }
            int flag = 0;
            for(int i = 0; i < n; i++) {
                if(~a[i]) {
                    int s = a[i]%n, t = i;
                    if(s <= t && pre[t]-(s==0?0:pre[s-1]) || s > t && pre[t]+pre[n-1]-pre[s-1]) {
                        flag = 1;
                        break;
                    }
                }
            }
            if(flag) {
                puts("-1");
                continue;
            }
            build(1, 0, n-1);
            for(int i = 0; i < n; i++) {
                if(~a[i]) {
                    int s = a[i]%n, t = i;
                    if(s < t) update(1, 0, n-1, s, t-1, pos[t]);
                    if(s > t) {
                        if(t > 0) update(1, 0, n-1, 0, t-1, pos[t]);
                        update(1, 0, n-1, s, n-1, pos[t]);
                    }
                }
            }
            P now;
            cnt = 0;
            while(!q.empty()) q.pop();
            for(int i = 0; i < n; i++) {
                if((~a[i]) && deg[pos[i]] == 0) q.push(make_pair(a[i], pos[i]));
            }
            while(!q.empty()) {
                now = q.top();
                q.pop();
                int u = now.second;
                if(~rt[u]) ans[++cnt] = now.first;
                for(int i = head[u]; ~i; i = nxt[i]) {
                    if(--deg[to[i]] == 0) {
                        if((~rt[to[i]]) && (~a[rt[to[i]]])) q.push(make_pair(a[rt[to[i]]], to[i]));
                        else if(rt[to[i]] == -1) q.push(make_pair(0, to[i]));
                    }
                }
            }
            if(cnt != n-pre[n-1]) {
                puts("-1");
                continue;
            }
            for(int i = 1; i <= cnt; i++) {
                printf("%d", ans[i]);
                if(i != cnt) printf(" ");
            }
            puts("");
        }
    }
    View Code
  • 相关阅读:
    C#事件理解
    二叉排序树查找算法代码
    二叉排序树查找算法代码
    深度学习——02、深度学习入门——卷积神经网络
    深度学习——02、深度学习入门——卷积神经网络
    程序员表白代码
    程序员表白代码
    程序员表白代码
    vbs实现消息轰炸
    vbs实现消息轰炸
  • 原文地址:https://www.cnblogs.com/Pneuis/p/9385563.html
Copyright © 2020-2023  润新知