牛客多校第四场 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,即序列不合法。
或拓扑排序出现环。
#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(线段树优化建图+拓扑排序)的更多相关文章
- 2018牛客多校第四场 J.Hash Function
题意: 给出一个已知的哈希表.求字典序最小的插入序列,哈希表不合法则输出-1. 题解: 对于哈希表的每一个不为-1的数,假如他的位置是t,令s = a[t]%n.则这个数可以被插入当且仅当第s ~ t ...
- 牛客多校第四场sequence C (线段树+单调栈)
牛客多校第四场sequence C (线段树+单调栈) 传送门:https://ac.nowcoder.com/acm/contest/884/C 题意: 求一个$\max {1 \leq l \le ...
- 2019年牛客多校第四场 B题xor(线段树+线性基交)
题目链接 传送门 题意 给你\(n\)个基底,求\([l,r]\)内的每个基底是否都能异或出\(x\). 思路 线性基交板子题,但是一直没看懂咋求,先偷一份咖啡鸡板子写篇博客吧~ 线性基交学习博客:传 ...
- 2019牛客多校第四场C-sequence(单调栈+线段树)
sequence 题目传送门 解题思路 用单调栈求出每个a[i]作为最小值的最大范围.对于每个a[i],我们都要乘以一个以a[i]为区间内最小值的对应的b的区间和s,如果a[i] > 0,则s要 ...
- 牛客多校第十场 F Popping Balloons 线段树维护稀疏矩阵
题意: 给定一个稀疏矩阵,里面有若干个气球,让你横着开三枪,竖着开三枪,问最多能打爆多少气球,要求相同方向,相邻两枪必须间隔r. 题解: 横向记录每列有多少个气球,分别在哪行上. 然后把这个数据改造成 ...
- 2019牛客多校第四场J free——分层图&&最短路
题意 一张无向图,每条边有权值,可以选择不超过 $k$ 条路使其权值变成0,求 $S$ 到 $T$ 的最短路.(同洛谷 P4568) 分析 首先,分层图最短路可以有效解决这种带有 「阶段性」的最短路, ...
- 牛客多校第四场 J Free 最短路
题意: 求最短路,但是你有k次机会可以把路径中某条边的长度变为0. 题解: 跑k+1次迪杰斯特拉,设想有k+1组dis数组和优先队列,第k组就意味着删去k条边的情况,每次松弛操作,松弛的两点i,j和距 ...
- 2019牛客多校第四场J free 最短路
free 题意 给出一个带权联通无向图,你需要从s走到t,你可以选择k条变让他们的权值为0问从s到t的最小权值是多少? 分析 思考一下,如果不带k条白嫖这个条件,那么这就是一个简单的dji就搞定了,我 ...
- 牛客多校第七场 C Governing sand 线段树
题意: 有一个树林,树林中不同种类的树有不同的数量,高度,砍伐它们的价格.现在要求砍掉一些树,使得高度最高的树占剩下的树的总数的一半以上,求最小花费. 题解: 用线段树维护不同种类树的信息,叶子节点从 ...
随机推荐
- PAT 1079 延迟的回文数(代码+思路)
1079 延迟的回文数(20 分) 给定一个 k+1 位的正整数 N,写成 ak⋯a1a0 的形式,其中对所有 i 有 0≤ai<10 且 ak>0.N 被称 ...
- Banner中文字怎么排版才好看?
今天这命题,相信有很多人提出过疑问,一个好的文字排版会给你的作品增添色彩,我们先看看好的作品是怎样的. 看完这些图大家都能感觉出来这是一个好的作品,大家天生就对美和丑有一定的区分. 其实文字排版也好, ...
- 2018.09.02 bzoj1025: [SCOI2009]游戏(计数dp+线筛预处理)
传送门 要将所有置换变成一个轮换,显然轮换的周期是所有置换长度的最小公倍数. 于是我们只需要求长度不超过n,且长度最小公倍数为t的不同置换数. 而我们知道,lcm只跟所有素数的最高位有关. 因此lcm ...
- 2018.07.17 洛谷P1368 工艺(最小表示法)
传送门 好的一道最小表示法的裸板,感觉跑起来贼快(写博客时评测速度洛谷第二),这里简单讲讲最小表示法的实现. 首先我们将数组复制一遍接到原数组队尾,然后维护左右指针分别表示两个即将进行比较的字符串的头 ...
- 实现WIFI MAC认证与漫游
前言 单位里有10来个网件的AP(WNAP210),需要对接入端(主要是手机)进行MAC认证,原来采用AP本地MAC认证,但是人员经常变动(离职),另外人员的岗位(流水线)也经常调整,这样就需在变动后 ...
- hadoop学习笔记(四):hdfs常用命令
一.hadoop fs 1.创建目录 [root@master hadoop-]# hadoop fs -mkdir /testdir1 [root@master hadoop-]# hadoop f ...
- java反编译工具jad使用
参考:http://blog.csdn.net/u014472711/article/details/53713269 http://lijingshou.iteye.com/blog/2005717 ...
- noip第10课作业
1. 统计不同类型字符出现次数 [问题描述] 输入一个字符串(假设长度不超过1000个字符),统计其中大写,小写,数字,其他字符出现的次数. [样例输入]Hello,what are you ...
- PAT甲 1006. Sign In and Sign Out (25) 2016-09-09 22:55 43人阅读 评论(0) 收藏
1006. Sign In and Sign Out (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue ...
- hdu 1300 Deck
题目 分析:对于n张卡片的最佳摆法,我们只需要在n-1张卡片的摆法下面加一张边缘与桌檐重合的卡片,并将所有卡片一起向桌檐外移动.对于一种最佳摆法,其中心一定在桌檐上,所以一定符合杠杆原理,支点是桌檐. ...