题目链接

题意 : 给出一个哈希表、其避免冲突的方法是线性探测再散列、现在问你给出的哈希表是否合法、如果合法则输出所有元素插入的顺序、如果有多解则输出字典序最小的那一个、如果不合法则输出 -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. PTA(Advanced Level)1036.Boys vs Girls

    This time you are asked to tell the difference between the lowest grade of all the male students and ...

  2. java crc32

      原文链接:http://blog.csdn.net/tbkken/article/details/8210952 在优化关系数据库的关联查询的时候,ON的字段选择为数值型,必须是会比字符型的数据快 ...

  3. 设计模式:备忘录模式(Memento)

    个人比较喜欢玩单机游戏,什么仙剑.古剑.鬼泣.使命召唤.三国无双等等一系列的游戏我都玩过(现在期待凡人修仙传),对于这些游戏除了剧情好.场面大.爽快之外,还可以随时存档,等到下次想玩了又可以从刚开始的 ...

  4. 从入门到自闭之Python闭包

    闭包 定义:在嵌套函数内,使用(非本层变量)非全局变量就是闭包 闭包必须是内层函数对外层函数的变量(非全局变量)的引用 函数执行完毕后,函数体内的空间自行销毁 def func(): a=1 def ...

  5. js 禁用F12 和右键查看源码

    <script> window.onkeydown = function(e) { if (e.keyCode === 123) { e.preventDefault() } } wind ...

  6. 16 Scrapy之分布式爬虫

    redis分布式部署 1.scrapy框架是否可以自己实现分布式? - 不可以.原因有二. 其一:因为多台机器上部署的scrapy会各自拥有各自的调度器,这样就使得多台机器无法分配start_urls ...

  7. 用原生JS写省市二级联动

    HTML代码 <select id="s1"> <option value="0">~请选择省份~</option> < ...

  8. angular装饰器

    @NgModule 元数据 NgModule 是一个带有 @NgModule() 装饰器的类.@NgModule() 装饰器是一个函数,它接受一个元数据对象,该对象的属性用来描述这个模块.其中最重要的 ...

  9. python之itertools

    Python的内建模块itertools提供了非常有用的用于操作迭代对象的函数. count 创建一个迭代器,生成从n开始的连续整数,如果忽略n,则从0开始计算(注意:此迭代器不支持长整数) 如果超出 ...

  10. multipart/form-data请求与文件上传的细节

    <!DOCTYPE html><html><head lang="en">  <meta charset="UTF-8" ...