题目链接

题意 : 给出一个哈希表、其避免冲突的方法是线性探测再散列、现在问你给出的哈希表是否合法、如果合法则输出所有元素插入的顺序、如果有多解则输出字典序最小的那一个、如果不合法则输出 -1

分析 : 

经过对样例的模拟和观察、可以发现

如果一个元素 A 本应去到的位置 pos 被元素 B 占据、则说明 B 要先于 A 进行放置

由于是采用线性再探测、所以从 pos 开始到 A 现在的位置 posNow 中经过的所有位置都应该先于 A 放置

例如 4 8 0 -1 在这个长度为 4 的哈希表中 0 元素本应在 0 这个位置、但是看到 4 在这个位置所以 4 要先于 0 插入

然后往前推移发现到 0 元素当前位置为止、还有一个 8 在、所以 8 也一个先于 0 插入

这给了我们一些启示、对于某个东西要在另一个东西之前执行

那么自然想到构建出前驱图、然后进行拓扑排序、如果拓扑排序成功则说明有解、否则无解(存在环)

要求字典序最小的话、使用队列构建拓扑排序选用的队列要改成优先队列

但是还有一个问题、实际上你会发现、每一次构建、都是一个区间的数连接到一个节点上

这样的建图、边会变得非常多、例如这种数据 1024、512、256、128、64、32、16、8 全部的哈希值都为 0

所以边会越来越多、接近 n ^ 2 建图、建图的复杂度就已经受不了了

所以需要一个优化、那就是线段树优化建图

适用于区间向区间、区间向点连边的情况

首先建线段树、长度为 1 ~ n

根据线段树在这题当中应用的意义

初始化每个节点都向其父亲连接一条边

表示子节点属于其父亲、这个是显然的

然后将原始的数组元素都赋值到线段树的叶子节点去

每一次区间向某一个数连边都可以变成某些表示此区间的线段树节点向表示这个数的叶子节点相连接

最后把建完成的前驱图 ( 也就是在原来线段树的每个节点上连出相对应的边 ) 跑拓扑排序即可

#include<bits/stdc++.h>
#define LL long long
#define ULL unsigned long long

#define scl(i) scanf("%lld", &i)
#define scll(i, j) scanf("%lld %lld", &i, &j)
#define sclll(i, j, k) scanf("%lld %lld %lld", &i, &j, &k)
#define scllll(i, j, k, l) scanf("%lld %lld %lld %lld", &i, &j, &k, &l)

#define scs(i) scanf("%s", i)
#define sci(i) scanf("%d", &i)
#define scd(i) scanf("%lf", &i)
#define scIl(i) scanf("%I64d", &i)
#define scii(i, j) scanf("%d %d", &i, &j)
#define scdd(i, j) scanf("%lf %lf", &i, &j)
#define scIll(i, j) scanf("%I64d %I64d", &i, &j)
#define sciii(i, j, k) scanf("%d %d %d", &i, &j, &k)
#define scddd(i, j, k) scanf("%lf %lf %lf", &i, &j, &k)
#define scIlll(i, j, k) scanf("%I64d %I64d %I64d", &i, &j, &k)
#define sciiii(i, j, k, l) scanf("%d %d %d %d", &i, &j, &k, &l)
#define scdddd(i, j, k, l) scanf("%lf %lf %lf %lf", &i, &j, &k, &l)
#define scIllll(i, j, k, l) scanf("%I64d %I64d %I64d %I64d", &i, &j, &k, &l)

#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
#define lowbit(i) (i & (-i))
#define mem(i, j) memset(i, j, sizeof(i))

#define fir first
#define sec second
#define VI vector<int>
#define ins(i) insert(i)
#define pb(i) push_back(i)
#define pii pair<int, int>
#define VL vector<long long>
#define mk(i, j) make_pair(i, j)
#define all(i) i.begin(), i.end()
#define pll pair<long long, long long>

#define _TIME 0
#define _INPUT 0
#define _OUTPUT 0
clock_t START, END;
void __stTIME();
void __enTIME();
void __IOPUT();
using namespace std;
;

VI ans;
int PreSum[maxn];
int arr[maxn];
int Node[maxn];
];
];

];
], EdgeCnt;

inline void init(int n)
{
    ans.clear();
    ; i<=(n<<); i++){
        IN[i] = ;
        Head[i] = -;
    }
    EdgeCnt = ;
}

inline void AddEdge(int from, int to)
{
    Edge[EdgeCnt].v = to;
    Edge[EdgeCnt].nxt = Head[from];
    Head[from] = EdgeCnt++;
    IN[to]++;
}

void Build(int l, int r, int rt)
{
    if(l == r){
        sci(arr[l]);
        PreSum[l] = PreSum[l-] + ( arr[l] == - );
        Node[l] = rt;
        Pos[rt] = l;
        return ;
    }

    Pos[rt] = ;
    AddEdge(rt<<|, rt);
    AddEdge(rt<<, rt);

    ;
    Build(lson);
    Build(rson);
}

void Connect(int L, int R, int c, int l, int r, int rt)
{
    if(L <= l && r <= R){
        AddEdge(rt, c);
        return ;
    }

    ;
    if(L <= m) Connect(L, R, c, lson);
    if(m < R) Connect(L, R, c, rson);
}

bool topo_sort(int n)
{
    priority_queue<pii, vector<pii>, greater<pii> > que;
    ; i<=n; i++){
        ){
            que.push(mk(arr[i], Node[i]));
        }
    }

    while(!que.empty()){
        pii top = que.top(); que.pop();

        ) ans.pb(top.fir);

        ; i=Edge[i].nxt){
            int Eiv = Edge[i].v;
            ){
                ) que.push(mk(arr[Pos[Eiv]], Eiv));
                , Eiv));
            }
        }
    }

    return ((int)ans.size() == n - PreSum[n]);
}

int main(void){__stTIME();__IOPUT();

    int nCase;
    sci(nCase);

    while(nCase--){

        int n;
        sci(n);

        init(n);

        Build(, n, );

        if(PreSum[n] == n) { puts(""); continue; }

        bool ok = true;
        ; i<=n; i++){
            ) continue;
            ) == i) continue;
            , R = (i - ) ==  ? n : i - ;
            if(L <= R){
                ] > ){ ok = false; break; }
                Connect(L, R, Node[i], , n, );
            }else{
                ] + PreSum[R] > ){ ok = false; break; }
                Connect(L, n, Node[i], , n, );
                Connect(, R, Node[i], , n, );
            }
        }

        if(!ok) puts("-1");
        else{
            if(!topo_sort(n)) puts("-1");
            ; i<(int)ans.size(); i++) printf("%d ", ans[i]); puts("");
        }
    }

__enTIME();;}

void __stTIME()
{
    #if _TIME
        START = clock();
    #endif
}

void __enTIME()
{
    #if _TIME
        END = clock();
        cerr<<"execute time = "<<(double)(END-START)/CLOCKS_PER_SEC<<endl;
    #endif
}

void __IOPUT()
{
    #if _INPUT
        freopen("in.txt", "r", stdin);
    #endif
    #if _OUTPUT
        freopen("out.txt", "w", stdout);
    #endif
}

Nowcoder Hash Function ( 拓扑排序 && 线段树优化建图 )的更多相关文章

  1. 【bzoj5017】[Snoi2017]炸弹 线段树优化建图+Tarjan+拓扑排序

    题目描述 在一条直线上有 N 个炸弹,每个炸弹的坐标是 Xi,爆炸半径是 Ri,当一个炸弹爆炸时,如果另一个炸弹所在位置 Xj 满足:  Xi−Ri≤Xj≤Xi+Ri,那么,该炸弹也会被引爆.  现在 ...

  2. 【bzoj4383】[POI2015]Pustynia 线段树优化建图+差分约束系统+拓扑排序

    题目描述 给定一个长度为n的正整数序列a,每个数都在1到10^9范围内,告诉你其中s个数,并给出m条信息,每条信息包含三个数l,r,k以及接下来k个正整数,表示a[l],a[l+1],...,a[r- ...

  3. BZOJ_4383_[POI2015]Pustynia_线段树优化建图+拓扑排序

    BZOJ_4383_[POI2015]Pustynia_线段树优化建图+拓扑排序 Description 给定一个长度为n的正整数序列a,每个数都在1到10^9范围内,告诉你其中s个数,并给出m条信息 ...

  4. 【2019.7.26 NOIP模拟赛 T3】化学反应(reaction)(线段树优化建图+Tarjan缩点+拓扑排序)

    题意转化 考虑我们对于每一对激活关系建一条有向边,则对于每一个点,其答案就是其所能到达的点数. 于是,这个问题就被我们搬到了图上,成了一个图论题. 优化建图 考虑我们每次需要将一个区间向一个区间连边. ...

  5. bzoj5017 [Snoi2017]炸弹 (线段树优化建图+)tarjan 缩点+拓扑排序

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=5017 题解 这个题目方法挺多的. 线段树优化建图 线段树优化建图的做法应该挺显然的,一个炸弹能 ...

  6. BZOJ5017 [SNOI2017]炸弹 - 线段树优化建图+Tarjan

    Solution 一个点向一个区间内的所有点连边, 可以用线段树优化建图来优化 : 前置技能传送门 然后就得到一个有向图, 一个联通块内的炸弹可以互相引爆, 所以进行缩点变成$DAG$ 然后拓扑排序. ...

  7. [Codeforces 1197E]Culture Code(线段树优化建图+DAG上最短路)

    [Codeforces 1197E]Culture Code(线段树优化建图+DAG上最短路) 题面 有n个空心物品,每个物品有外部体积\(out_i\)和内部体积\(in_i\),如果\(in_i& ...

  8. 【ARC069F】Flags 2-sat+线段树优化建图+二分

    Description ​ 数轴上有 n 个旗子,第 ii 个可以插在坐标 xi或者 yi,最大化两两旗子之间的最小距离. Input ​ 第一行一个整数 N. ​ 接下来 N 行每行两个整数 xi, ...

  9. 【BZOJ3681】Arietta 树链剖分+可持久化线段树优化建图+网络流

    [BZOJ3681]Arietta Description Arietta 的命运与她的妹妹不同,在她的妹妹已经走进学院的时候,她仍然留在山村中.但是她从未停止过和恋人 Velding 的书信往来.一 ...

随机推荐

  1. Java小知识----List复制:浅拷贝与深拷贝

    原文地址: https://blog.csdn.net/demonliuhui/article/details/54572908 List浅拷贝 众所周知,list本质上是数组,而数组的是以地址的形式 ...

  2. 浅谈Linux du命令

    **du(disk usage),顾名思义,查看目录/文件占用空间大小** 1.查看当前目录下的所有目录以及子目录的大小  du -h du -ah #-h:用K.M.G的人性化形式显示#-a:显示目 ...

  3. FFmpeg4.0笔记:采集系统声音

    Github https://github.com/gongluck/FFmpeg4.0-study/tree/master/Cff // 采集系统声音 void test_systemsound() ...

  4. Tomcat的安全性

    Web应用程序的一些内容是受限的,只有授权的用户在提供了正确的用户名和密码后才能查看他们,servlet技术支持通过配置部署 描述器(web.xml)来对这些内容进行访问控制,那么web容器是怎么样支 ...

  5. 同步(Synchronous)和异步(Asynchronous)方法的区别

    同步(Synchronous)和异步(Asynchronous)方法的区别 在讲之前,我们先来看<Computer Organization>中对于同步和异步的一个例子: 同步读写和异步读 ...

  6. EF报错:对一个或多个实体的验证失败(Entity Framework 强制转换失败数据异常处理方法)

    1.使用MVC和EF,在保存数据的时候报错:System.Data.Entity.Validation.DbEntityValidationException: 对一个或多个实体的验证失败.有关详细信 ...

  7. LRU算法介绍和在JAVA的实现及源码分析

    一.写随笔的原因:最近准备去朋友公司面试,他说让我看一下LRU算法,就此整理一下,方便以后的复习. 二.具体的内容: 1.简介: LRU是Least Recently Used的缩写,即最近最少使用. ...

  8. linux下如何查询jdk的安装路径

    首先这个问题困扰了我很久,由于是新装的系统还不熟悉,配置java环境变量时很头疼,找不到JDK位置,还好google一波,发现了这个方法. 首先确保安装了JDK java -version java ...

  9. 31、NTP时间服务器

    1.NTP简介 NTP服务器顾名思义就是时间同步服务器(Network Time Protocol),Linux下的ntp服务器配置相对来说都比较容易,但在Linux下有一个弊端,不同时区或者说是时间 ...

  10. linux下测试web访问及网络相关的命令

    curl命令 curl是linux系统命令行下用来简单测试web访问的工具. curl -xip:port www.baidu.com    -x可以指定ip和端口,省略写hosts,方便实用 -I  ...