【AtCoder Grand Contest 001F】Wide Swap [线段树][拓扑]
Wide Swap
Time Limit: 50 Sec Memory Limit: 512 MB
Description

Input

Output

Sample Input
8 3
4 5 7 8 3 1 2 6
Sample Output
1
2
6
7
5
3
4
8
HINT

Solution
首先,直接做难度系数较高,假设原序列为a,我们考虑设一个p,p[a_i] = i,即将题目中的权值与下标调换。
那么显然,要令a字典序最小,只要让p字典序最小即可。因为“权值小的尽量前”与“前面的权值尽量小”是一个意思。
现在操作转化为:相邻元素且权值差>=k的可以换顺序。
考虑一个暴力怎么做,显然是 i 与后面的所有 j 比,如果 abs(p_i - p_j) < k,则 i 和 j 的相对顺序就确定了, 连一条 p_i -> p_j 的边。
连边之后跑一边拓扑即可。
显然复杂度在于连边,因为这样暴力会有很多无用边。比如A->B, B->C, A->C,这条A->C显然无用。
我们考虑如何删掉 A->C 这种边。
倒着加入,显然 p_i 连向 (p_i-k, p_i)∪(p_i, p_i+k)。我们只需要分别连向两个区间中下标最小的那一个即可。用线段树维护一下区间最小值。
Code
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<queue>
using namespace std;
typedef long long s64; #define next nxt
const int ONE = ;
const int INF = ; int get()
{
int res = , Q = ; char c;
while( (c = getchar()) < || c > )
if(c == '-') Q = -;
if(Q) res = c - ;
while( (c = getchar()) >= && c <= )
res = res * + c - ;
return res * Q;
} int n, k;
int A[ONE], p[ONE];
int next[ONE], first[ONE], go[ONE], Input[ONE], tot;
priority_queue <int, vector <int>, greater <int> > q; int res = INF;
namespace Seg
{
struct power {int val;} Node[ONE * ];
void Build(int i, int l, int r)
{
Node[i].val = INF;
if(l == r) return;
int mid = l + r >> ;
Build(i << , l, mid), Build(i << | , mid + , r);
} void Update(int i, int l, int r, int L, int x)
{
if(L <= l && r <= L)
{
Node[i].val = x;
return;
}
int mid = l + r >> ;
if(L <= mid) Update(i << , l, mid, L, x);
else Update(i << | , mid + , r, L, x);
Node[i].val = min(Node[i << ].val, Node[i << | ].val);
} void Query(int i, int l, int r, int L, int R)
{
if(L > R) return;
if(L <= l && r <= R)
{
res = min(res, Node[i].val);
return;
}
int mid = l + r >> ;
if(L <= mid) Query(i << , l, mid, L, R);
if(mid + <= R) Query(i << | , mid + , r, L, R);
}
} void Add(int u, int v)
{
Input[v]++, next[++tot] = first[u], first[u] = tot, go[tot] = v;
} void Deal()
{
int now = ;
for(int i = ; i <= n; i++)
if(!Input[i]) q.push(i);
while(!q.empty())
{
int u = q.top(); q.pop();
A[u] = ++now;
for(int e = first[u]; e; e = next[e])
{
int v = go[e];
if(--Input[v] == ) q.push(v);
}
}
for(int i = ; i <= n; i++) printf("%d\n", A[i]);
} int main()
{
n = get(), k = get();
for(int i = ; i <= n; i++) p[get()] = i; Seg::Build(, , n);
for(int i = n; i >= ; i--)
{
res = INF, Seg::Query(, , n, p[i] + , min(p[i] + k - , n));
if(res != INF) Add(p[i], p[res]); res = INF, Seg::Query(, , n, max(, p[i] - k + ), p[i] - );
if(res != INF) Add(p[i], p[res]); Seg::Update(, , n, p[i], i);
} Deal();
}
【AtCoder Grand Contest 001F】Wide Swap [线段树][拓扑]的更多相关文章
- AtCoder Grand Contest 001F Wide Swap
解法参考这位大佬的:https://www.cnblogs.com/BearChild/p/7895719.html 因为原来的数组不好做于是我们想反过来数组,根据交换条件:值相邻且位置差大于等于k, ...
- AtCoder AGC001F Wide Swap (线段树、拓扑排序)
题目链接: https://atcoder.jp/contests/agc001/tasks/agc001_f 题解: 先变成排列的逆,要求\(1\)的位置最小,其次\(2\)的位置最小,依次排下去( ...
- AtCoder Grand Contest 001 C Shorten Diameter 树的直径知识
链接:http://agc001.contest.atcoder.jp/tasks/agc001_c 题解(官方): We use the following well-known fact abou ...
- AtCoder Grand Contest 011
AtCoder Grand Contest 011 upd:这篇咕了好久,前面几题是三周以前写的... AtCoder Grand Contest 011 A - Airport Bus 翻译 有\( ...
- AtCoder Grand Contest 009
AtCoder Grand Contest 009 A - Multiple Array 翻译 见洛谷 题解 从后往前考虑. #include<iostream> #include< ...
- AtCoder Grand Contest 005
AtCoder Grand Contest 005 A - STring 翻译 给定一个只包含\(ST\)的字符串,如果出现了连续的\(ST\),就把他删去,然后所有位置前移.问最后剩下的串长. 题解 ...
- AtCoder Grand Contest 004
AtCoder Grand Contest 004 A - Divide a Cuboid 翻译 给定一个\(A*B*C\)的立方体,现在要把它分成两个立方体,求出他们的最小体积差. 题解 如果有一条 ...
- AtCoder Grand Contest 014
AtCoder Grand Contest 014 A - Cookie Exchanges 有三个人,分别有\(A,B,C\)块饼干,每次每个人都会把自己的饼干分成相等的两份然后给其他两个人.当其中 ...
- AtCoder Grand Contest 012
AtCoder Grand Contest 012 A - AtCoder Group Contest 翻译 有\(3n\)个人,每一个人有一个强大值(看我的假翻译),每三个人可以分成一组,一组的强大 ...
随机推荐
- mongodb授权认证 介绍
mongodb存储所有的用户信息在admin 数据库的集合system.users中,保存用户名.密码和数据库信息.mongodb默认不启用授权认证,只要能连接到该服务器,就可连接到mongod.若要 ...
- [2017BUAA软工]第2次个人作业
软工第2次个人作业--代码复审 一.代码复审Check List 1.概要部分 代码能符合需求和规格说明么? 能正确处理题目要求,代码能符合需求和规格. 代码设计是否有周全的考虑? 能正确生成和解出数 ...
- win10频繁提示证书即将过期怎么办
最近几天每次开机都会提示许可证即将过期 ”Windows+R”打开“运行”窗口,输入“slmgr.vbs -xpr”并点击“确定”,弹出的窗口确实显示过期时间在本月1.29过期 百度各种激活方法后,发 ...
- HDU 1027 打印沙漏
https://pintia.cn/problem-sets/994805260223102976/problems/994805294251491328 本题要求你写个程序把给定的符号打印成沙漏的形 ...
- python读取文件解码失败
python2.7 urllib2 抓取新浪乱码 中的: 报错的异常是 UnicodeDecodeError: 'gbk' codec can't decode bytes in position 2 ...
- hdu 1556 Color the ball(树状数组)
链接:http://acm.hdu.edu.cn/showproblem.php?pid=1556 题意:N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数[a,b]之间的气球 ...
- 我项目中使用userData的实例 UserData.js
关于userData的介绍,请参见http://hi.baidu.com/kaisep/blog/item/1da9a3312d2da5a15edf0e87.htmlhttp://hi.baidu.c ...
- [洛谷P4819][中山市选]杀人游戏
题目大意:有一张$n$个点$m$条边的有向图,有一个关键点,如果你访问一个点,你会知道它连出的边中有没有关键点,以及若有的话是哪个.问最优策略下不访问关键点而知道关键点的概率 题解:发现若一个点不是关 ...
- kafka-connect-hive Sink插件入门指南
kafka-connect-hive是基于kafka-connect平台实现的hive数据读取和写入插件,主要由source.sink两部分组成,source部分完成hive表数据的读取任务,kafk ...
- HNOI2018毒瘤
题面链接 luogu sol 这篇博是骗访问量的QwQ. 考虑树怎么做,简单容斥.诸如\(f[u][0]=\prod (f[v][0]+f[v][1]),f[u][1]=\prod f[v][0]\) ...