여름 학교 오프 이상 2018 소 : 해쉬 함수 [그림 + 세그먼트 트리 최적화 위상 정렬을 내장]

주제 :

2018 가축 오프 더 학교 네 번째 필드 : 해쉬 함수

질문의 의미 :

충돌이 없을 때까지 알려진 해시 함수의 해시 (X) = X 개조 N, 해시 충돌이 발생하는 경우, 해시 (X) = 해시 (X + 1), 지금 전적으로 출력 해시 테이블을 주어진 최소 삽입 계열

분석 :

X는 해시 (x)에 위치되지 않으면, 해쉬 [X] 모든 숫자가 처음 률 X를 삽입해야하는 위치 (x)에, 위상 정렬의 실행을 용이하게 구축 내지도 발생할 수 있지만, 직접도 복잡성 N ^ 2 내장 범위의 시점 트리 각 트리 라인의 노드와 아버지라도 일방 측의 지점이 세그먼트의 정도 맵을 고려하여 시공면의주기이기 때문에, (두 아들 아버지 능력을 가지고 ), 대응 노드 측 주를 구축 할 수있는 모서리를 찾아 지어진 : 그것은 불법 간격 일 수 있으며, 시간 간격은 프리픽스 가득 잘 최소 사전적인 우선 립 노드의 값을 결정되지

코드 :

#include <bits/stdc++.h>

using namespace std;
const int maxn = 2e6+255;
int tr[maxn<<2],a[maxn],sum[maxn],T,n;
struct edge{
    int to,nxt;
}e[maxn<<2];
int head[maxn<<2],cnt,pos[maxn<<2],val[maxn<<2],in[maxn<<2],vis[maxn<<2],num;
inline void add(int u,int v){
    e[++cnt].to = v;
    e[cnt].nxt = head[u];
    head[u] = cnt;
    in[v]++;
}
void build(int l,int r,int x){
    num++; val[x] = -1; vis[x] = 1;  //num记录总结点的个数,vis标记那些节点使用了
    if(l == r){
        pos[l] = x;
        val[x] = a[l];
        return ;
    }
    int mid = (l+r) >> 1;
    build(l,mid,x<<1);
    build(mid+1,r,x<<1|1);
    add(x<<1,x);add(x<<1|1,x);
}
void Updata(int l,int r,int L,int R,int x,int u){
    if(L > R) return;
    if(l > R || r < L) return ;
    if(l >= L && r <= R){
        add(x,u);
        return ;
    }
    int mid = (l+r) >> 1;
    Updata(l,mid,L,R,x<<1,u);
    Updata(mid+1,r,L,R,x<<1|1,u);
}
struct node{
    int x;
    friend bool operator <(node a,node b){
        return val[a.x] > val[b.x];
    }
};
vector<int> ans;

bool spafa(){
    priority_queue<node> q;
    int sum = 0;
    for(int i = 1;i <= (n<<2); ++i) if(!in[i]&&vis[i]) q.push(node{i});
    while(!q.empty()){
        node u = q.top();q.pop();
        sum++;
        if(~val[u.x]) ans.push_back(val[u.x]);
        for(int i = head[u.x]; i;i = e[i].nxt){
            int v = e[i].to;
            if(--in[v] == 0) q.push(node{v});
        }
    }
    return sum == num;
}
void init(int n){
    ans.clear();cnt = num = 0;
    for(int i = 0;i <= (n<<2); ++i) 
        head[i] = vis[i] = in[i] = 0;
}
int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        init(n);
        for(int i = 1;i <= n; ++i) scanf("%d",a+i);
        for(int i = 1;i <= n; ++i){
            sum[i] = sum[i-1];
            if(~a[i]) sum[i]++;
        }
        build(1,n,1); bool flag = true;
        for(int i = 1;i <= n && flag; ++i){
            if(~a[i]){
                int tep = a[i] % n + 1;
                if(i > tep) {
                    Updata(1,n,tep,i-1,1,pos[i]);
                    if(sum[i-1]-sum[tep-1] != i-tep) flag = false;
                }
                else if(i < tep){
                    Updata(1,n,tep,n,1,pos[i]);
                    if(sum[n]-sum[tep-1] != n-tep+1) flag = false;
                    Updata(1,n,1,i-1,1,pos[i]);
                    if(sum[i-1] != i-1) flag = false;
                }
            }
        }
        if(flag&&spafa()){
            for(int i = 0;i < (int)ans.size(); ++i) printf("%d ", ans[i]);
            putchar('\n');
        }
        else puts("-1");
    }
    return 0;
}

 

추천

출처blog.csdn.net/qq_41157137/article/details/92253553