题目传送门: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,即序列不合法。

或拓扑排序出现环。

 #include <bits/stdc++.h>
#define maxn 200005
using namespace std;
typedef pair<int,int> pii;
int fix[maxn],a[maxn];
int pos[maxn<<],id[maxn<<];
int deg[maxn<<];
vector<int> G[maxn<<];
int n;
void init(int n){
memset(deg,,sizeof(int)*(n<<|));
for (int i=;i<(n<<|);i++) G[i].clear();
}
void addedge(int u,int v){
G[u].push_back(v);
deg[v]++;
}
void build(int root,int l,int r){
id[root]=-;
if (l==r){
pos[l]=root;
id[root]=l;
return ;
}
int mid=(l+r)/;
addedge(root<<,root);
addedge(root<<|,root);
build(root<<,l,mid);
build(root<<|,mid+,r);
}
int judge(int s,int t){
if (s<=t) return (fix[t]-fix[s]==) && (a[s]!=-);
else return (fix[n-]-fix[s-]==) && !fix[t];
}
void Addedge(int L,int R,int p,int root,int l,int r){
if (L<=l && r<=R){
addedge(root,p);
return ;
}
int mid=(l+r)/;
if (L<=mid) Addedge(L,R,p,root<<,l,mid);
if (R>mid) Addedge(L,R,p,root<<|,mid+,r);
}
void topo(){
priority_queue<pii,vector<pii>,greater<pii> > Q;
for (int i=;i<n;i++)
if (!deg[pos[i]]) Q.push({a[i],pos[i]});
vector<int> ans;
while (!Q.empty()){
pii pos=Q.top();
Q.pop();
int u=pos.second;
if (pos.first!=-) ans.push_back(pos.first);
int v;
for (auto v : G[u]){
if (--deg[v]==){
if (id[v]==-) Q.push({-,v});
else Q.push({a[id[v]],v});
}
}
}
if (ans.size()!=n-fix[n-]){
cout << - << endl;
return ;
}
if (ans.size()==){
cout << endl;
return ;
}
for (int i=;i<ans.size();i++){
if (i==) cout << ans[i];
else cout << " " << ans[i];
}
cout << endl;
return ;
}
int main(){
int t;
cin >> t;
while (t--){
cin >> n;
init(n);
for (int i=;i<n;i++){
cin >> a[i];
if (i) fix[i]=fix[i-]+(a[i]==-);
else fix[i]=(a[i]==-);
}
int flag=;
for (int i=;i<n;i++){
if (a[i]!=- && !judge(a[i]%n,i)){
cout << - << endl;
flag=;
break;
}
}
if (flag) continue;
build(,,n-);
for (int i=;i<n;i++){
if (a[i]!=-){
int s=a[i]%n,t=i;
if (s==t) continue;
if (s<t){
Addedge(s,t-,pos[i],,,n-);
}
else{
if (t) Addedge(,t-,pos[i],,,n-);
Addedge(s,n-,pos[i],,,n-);
}
}
}
topo();
}
return ;
}

牛客多校第四场 J.Hash Function(线段树优化建图+拓扑排序)的更多相关文章

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

    题意: 给出一个已知的哈希表.求字典序最小的插入序列,哈希表不合法则输出-1. 题解: 对于哈希表的每一个不为-1的数,假如他的位置是t,令s = a[t]%n.则这个数可以被插入当且仅当第s ~ t ...

  2. 牛客多校第四场sequence C (线段树+单调栈)

    牛客多校第四场sequence C (线段树+单调栈) 传送门:https://ac.nowcoder.com/acm/contest/884/C 题意: 求一个$\max {1 \leq l \le ...

  3. 2019年牛客多校第四场 B题xor(线段树+线性基交)

    题目链接 传送门 题意 给你\(n\)个基底,求\([l,r]\)内的每个基底是否都能异或出\(x\). 思路 线性基交板子题,但是一直没看懂咋求,先偷一份咖啡鸡板子写篇博客吧~ 线性基交学习博客:传 ...

  4. 2019牛客多校第四场C-sequence(单调栈+线段树)

    sequence 题目传送门 解题思路 用单调栈求出每个a[i]作为最小值的最大范围.对于每个a[i],我们都要乘以一个以a[i]为区间内最小值的对应的b的区间和s,如果a[i] > 0,则s要 ...

  5. 牛客多校第十场 F Popping Balloons 线段树维护稀疏矩阵

    题意: 给定一个稀疏矩阵,里面有若干个气球,让你横着开三枪,竖着开三枪,问最多能打爆多少气球,要求相同方向,相邻两枪必须间隔r. 题解: 横向记录每列有多少个气球,分别在哪行上. 然后把这个数据改造成 ...

  6. 2019牛客多校第四场J free——分层图&&最短路

    题意 一张无向图,每条边有权值,可以选择不超过 $k$ 条路使其权值变成0,求 $S$ 到 $T$ 的最短路.(同洛谷 P4568) 分析 首先,分层图最短路可以有效解决这种带有 「阶段性」的最短路, ...

  7. 牛客多校第四场 J Free 最短路

    题意: 求最短路,但是你有k次机会可以把路径中某条边的长度变为0. 题解: 跑k+1次迪杰斯特拉,设想有k+1组dis数组和优先队列,第k组就意味着删去k条边的情况,每次松弛操作,松弛的两点i,j和距 ...

  8. 2019牛客多校第四场J free 最短路

    free 题意 给出一个带权联通无向图,你需要从s走到t,你可以选择k条变让他们的权值为0问从s到t的最小权值是多少? 分析 思考一下,如果不带k条白嫖这个条件,那么这就是一个简单的dji就搞定了,我 ...

  9. 牛客多校第七场 C Governing sand 线段树

    题意: 有一个树林,树林中不同种类的树有不同的数量,高度,砍伐它们的价格.现在要求砍掉一些树,使得高度最高的树占剩下的树的总数的一半以上,求最小花费. 题解: 用线段树维护不同种类树的信息,叶子节点从 ...

随机推荐

  1. db2 创建用户及授权

    1.创建系统用户dbuser/ehong隶属于db2users 2.C:\Program Files\IBM\SQLLIB\BIN>db2 connect to AKZXTEST数据库连接信息  ...

  2. 开发中常遇到的Python陷阱和注意点-乾颐堂

    最近使用Python的过程中遇到了一些坑,例如用datetime.datetime.now()这个可变对象作为函数的默认参数,模块循环依赖等等. 在此记录一下,方便以后查询和补充. 避免可变对象作为默 ...

  3. Netty系列(四)TCP拆包和粘包

    Netty系列(四)TCP拆包和粘包 一.拆包和粘包问题 (1) 一个小的Socket Buffer问题 在基于流的传输里比如 TCP/IP,接收到的数据会先被存储到一个 socket 接收缓冲里.不 ...

  4. 03 Maven 坐标与依赖

    Maven 坐标与依赖 Maven 的一大功能是管理项目依赖.为了能自动化地解析任何一个 Java 构件, Maven 就必须将它们唯一标识,这就依赖管理的底层基础 一一 坐标.本章将详细分析 Mav ...

  5. Directory /usr/local/hadoop/tmp/tmp/hadoop-root/dfs/name is in an inconsistent state: storage directory does not exist or is not accessible

    解决方法: <property> <name>hadoop.tmp.dir</name> <value>/usr/local/hadoop/tmp< ...

  6. 【JDBC&Dbutils】JDBC&JDBC连接池&DBUtils使用方法(重要)

    -----------------------JDBC---------- 0.      db.properties文件 driver=com.mysql.jdbc.Driver url=jdbc: ...

  7. 2018.10.12 NOIP模拟 字符处理(模拟)

    传送门 sb模拟,考试跟着sb了90分. 代码

  8. 2018.07.12 atcoder Go Home(贪心)

    传送门 题意简述:大家在数轴上生活,公司在 s. 班车送所有人回家,有 n 个住处,第 i 个位置在 xi,居住了 pi 的人. 保证 xi 互不相同. 大家⼀起投票向前还是向后,如果票数相同就固定向 ...

  9. vc中使用SendMessage正确发送自定义消息的方法

    最近在用VC2008做开发,后来由于要用到消息的发送,而且需要自定义消息,在网上查找了很多例子,根据他们所说的,虽然大致都差不多,但是基本上没有 一个能完全做出来的.要知道VC编程有一个小地方出错,都 ...

  10. no_namespace rename 在C++中是什么意思啊

    #import "C:\Program Files\Common Files\System\ado\msado15.dll" no_namespace rename("E ...