zoukankan      html  css  js  c++  java
  • 牛客多校第四场 J.Hash Function(线段树优化建图+拓扑排序)

    题目传送门:https://www.nowcoder.com/acm/contest/142/J

    题意:给一个hash table,求出字典序最小的插入序列,或者判断不合法。

    分析:

    eg.对于序列{7,8,16},插入后为{16, -1, -1, -1, -1, -1, -1, 7, 8}。(即,依次插入7,8,16。而插入16时发现7已经被占,所以依次考虑(h(x)+1)%n ,因此16放在0的位置上。)这是正向插入,问题是给一个最终序列,问插入序列。

    通过对hash表的观察可以得到:

    一个区间里的数一定比单独一个数插入更早。

     

    1.存在答案:

    那么就会存在对于每一个数a[i],存在两个位置s=a[i]%n,即本应该放在的位置。和t=i,即实际放在的位置。

     

    朴素O(n^2)建图:

    每找到一个数字s!=t,那么向前建边。若s==t,不需要建边。然后每次选择度数为0的点中最小的数(保证字典序min),然后把与该点相连的所有边删去。

     

    通过上述朴素建图,发现每个点所建边的是一段区间内的所有点。引出:

    线段树O(n)优化建图:

    同上,若一个点需要连向一个区间,就向线段树上的这个区间连边。然后把度数为0的点一一删去,即把线段树内对应的叶子节点清空,然后向上更新。当一个区间为空时,就把所有连向这个点的所有边删掉了。

    ps.一个点最多会向线段树上logn个区间,即logn个点相连。

     

    2.判断不合法:

    在区间[s,t)内存在-1,即序列不合法。

    或拓扑排序出现环。

     

      1 #include <bits/stdc++.h>
      2 #define maxn 200005
      3 using namespace std;
      4 typedef pair<int,int> pii;
      5 int fix[maxn],a[maxn];
      6 int pos[maxn<<2],id[maxn<<2];
      7 int deg[maxn<<2];
      8 vector<int> G[maxn<<2]; 
      9 int n;
     10 void init(int n){
     11     memset(deg,0,sizeof(int)*(n<<2|5));
     12     for (int i=0;i<(n<<2|5);i++) G[i].clear();
     13 }
     14 void addedge(int u,int v){
     15     G[u].push_back(v);
     16     deg[v]++;
     17 }
     18 void build(int root,int l,int r){
     19     id[root]=-1;
     20     if (l==r){
     21         pos[l]=root;
     22         id[root]=l;
     23         return ;
     24     }
     25     int mid=(l+r)/2;
     26     addedge(root<<1,root);
     27     addedge(root<<1|1,root);
     28     build(root<<1,l,mid);
     29     build(root<<1|1,mid+1,r); 
     30 }
     31 int judge(int s,int t){
     32     if (s<=t) return (fix[t]-fix[s]==0) && (a[s]!=-1);
     33     else return (fix[n-1]-fix[s-1]==0) && !fix[t];
     34 }
     35 void Addedge(int L,int R,int p,int root,int l,int r){
     36     if (L<=l && r<=R){
     37         addedge(root,p);
     38         return ;
     39     }
     40     int mid=(l+r)/2;
     41     if (L<=mid) Addedge(L,R,p,root<<1,l,mid);
     42     if (R>mid) Addedge(L,R,p,root<<1|1,mid+1,r);
     43 }
     44 void topo(){
     45     priority_queue<pii,vector<pii>,greater<pii> > Q;
     46     for (int i=0;i<n;i++)
     47         if (!deg[pos[i]]) Q.push({a[i],pos[i]});
     48     vector<int> ans;
     49     while (!Q.empty()){
     50         pii pos=Q.top();
     51         Q.pop();
     52         int u=pos.second;
     53         if (pos.first!=-1) ans.push_back(pos.first);
     54         int v;
     55         for (auto v : G[u]){
     56             if (--deg[v]==0){
     57                 if (id[v]==-1) Q.push({-1,v});
     58                 else Q.push({a[id[v]],v});
     59             }
     60         }
     61     }
     62     if (ans.size()!=n-fix[n-1]){
     63         cout << -1 << endl;
     64         return ;
     65     }
     66     if (ans.size()==0){
     67         cout << endl;
     68         return ;
     69     }
     70     for (int i=0;i<ans.size();i++){
     71         if (i==0) cout << ans[i];
     72         else cout << " " << ans[i];
     73     }
     74     cout << endl;
     75     return ;
     76 }
     77 int main(){
     78     int t;
     79     cin >> t;
     80     while (t--){
     81         cin >> n;
     82         init(n);
     83         for (int i=0;i<n;i++){
     84             cin >> a[i];
     85             if (i) fix[i]=fix[i-1]+(a[i]==-1);
     86             else fix[i]=(a[i]==-1);
     87         }
     88         int flag=0;
     89         for (int i=0;i<n;i++){
     90             if (a[i]!=-1 && !judge(a[i]%n,i)){
     91                 cout << -1 << endl;
     92                 flag=1;
     93                 break;
     94             }
     95         }
     96         if (flag) continue;
     97         build(1,0,n-1);
     98         for (int i=0;i<n;i++){
     99             if (a[i]!=-1){
    100                 int s=a[i]%n,t=i;
    101                 if (s==t) continue;
    102                 if (s<t){
    103                     Addedge(s,t-1,pos[i],1,0,n-1);
    104                 }
    105                 else{
    106                     if (t) Addedge(0,t-1,pos[i],1,0,n-1);
    107                     Addedge(s,n-1,pos[i],1,0,n-1);
    108                 }
    109             }
    110         }
    111         topo();
    112     }
    113     return 0;
    114 }

     

     

  • 相关阅读:
    Bower 使用
    为什么是static?
    多重继承 -Javascript中的apply与call详解
    留用 未验证 js适配根字体大小
    Js作用域与作用域链详解
    理解AngularJS中的依赖注入
    渐进增强 优雅降级
    前后台数据交换的几种方式:
    then()方法是异步执行
    HTML怎么让img 等比例缩放
  • 原文地址:https://www.cnblogs.com/changer-qyz/p/9385674.html
Copyright © 2011-2022 走看看