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,我们考虑设一个pp[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 [线段树][拓扑]的更多相关文章

  1. AtCoder Grand Contest 001F Wide Swap

    解法参考这位大佬的:https://www.cnblogs.com/BearChild/p/7895719.html 因为原来的数组不好做于是我们想反过来数组,根据交换条件:值相邻且位置差大于等于k, ...

  2. AtCoder AGC001F Wide Swap (线段树、拓扑排序)

    题目链接: https://atcoder.jp/contests/agc001/tasks/agc001_f 题解: 先变成排列的逆,要求\(1\)的位置最小,其次\(2\)的位置最小,依次排下去( ...

  3. AtCoder Grand Contest 001 C Shorten Diameter 树的直径知识

    链接:http://agc001.contest.atcoder.jp/tasks/agc001_c 题解(官方): We use the following well-known fact abou ...

  4. AtCoder Grand Contest 011

    AtCoder Grand Contest 011 upd:这篇咕了好久,前面几题是三周以前写的... AtCoder Grand Contest 011 A - Airport Bus 翻译 有\( ...

  5. AtCoder Grand Contest 009

    AtCoder Grand Contest 009 A - Multiple Array 翻译 见洛谷 题解 从后往前考虑. #include<iostream> #include< ...

  6. AtCoder Grand Contest 005

    AtCoder Grand Contest 005 A - STring 翻译 给定一个只包含\(ST\)的字符串,如果出现了连续的\(ST\),就把他删去,然后所有位置前移.问最后剩下的串长. 题解 ...

  7. AtCoder Grand Contest 004

    AtCoder Grand Contest 004 A - Divide a Cuboid 翻译 给定一个\(A*B*C\)的立方体,现在要把它分成两个立方体,求出他们的最小体积差. 题解 如果有一条 ...

  8. AtCoder Grand Contest 014

    AtCoder Grand Contest 014 A - Cookie Exchanges 有三个人,分别有\(A,B,C\)块饼干,每次每个人都会把自己的饼干分成相等的两份然后给其他两个人.当其中 ...

  9. AtCoder Grand Contest 012

    AtCoder Grand Contest 012 A - AtCoder Group Contest 翻译 有\(3n\)个人,每一个人有一个强大值(看我的假翻译),每三个人可以分成一组,一组的强大 ...

随机推荐

  1. sed ,awk , cut三剑客的区别

    sed: sed只能截取文件中以行的来截取数据,,(grep命令可以过滤到某一行) 例如: [root@localhost ~]# sed  -n  '2,3p'  /etc/passwd       ...

  2. [转帖]超能课堂 CPU制作过程

    http://www.expreview.com/50814.html 一般来说,我们对IC芯片的了解仅限于它概念,但是对于已经应用到各式各样的数码产品中IC芯片是怎么来的?大家可能只知道制作IC芯片 ...

  3. 实现LinearLayout(垂直布局,Gravity内容排布)

    首先上Gravity的代码,Android原版的Gravity搞得挺复杂的,太高端了.但基本思路是使用位运算来做常量,我就自己消化了一些,按自己的思路来实现. 先上代码,在做分析. package k ...

  4. uva 1513(线段树)

    题目链接:1513 - Movie collection 题意:有一堆电影,按1-n顺序排,有m次操作,每次询问第ai个电影之前有多少个电影,然后将其抽出放在堆顶. 分析:线段树应用. 因为每次查询后 ...

  5. day1 学习历程

    day1 我是一个在校大三学生,一个依然迷茫不知前景的大学混子= =,可以这么说吧 大学混子 真正开始决定好好学习大概在去年的12月份 那时经老师的提醒 开始正式接触软件开发 于是 从头开始学习语言 ...

  6. 对final和static的理解

    一.final (一).final的使用 final关键字可以用来修饰类.方法和变量(包括成员变量和局部变量) 1. 当用final修饰一个类时,表明这个类不能被继承.2. 当用final修饰一个方法 ...

  7. BZOJ4519 CQOI2016不同的最小割(最小割+分治)

    最小割树:新建一个图,包含原图的所有点,初始没有边.任取两点跑最小割,给两点连上权值为最小割的边,之后对于两个割集分别做同样的操作.最后会形成一棵树,树上两点间路径的最小值即为两点最小割.证明一点都不 ...

  8. python使用selenium、PhantomJS获得网站cookie信息#windows

    首先python安装selenium,命令行中输入 pip install selenium 在执行代码如下代码时出现错误 driver=webdriver.PhantomJS() 错误如下 sele ...

  9. 整理:python的二维数组操作

    Python中初始化一个5 x 3每项为0的数组,最好方法是: multilist = [[0 for col in range(5)] for row in range(3)] 如果初始化一个二维数 ...

  10. Statement和PreparedStatement之间的区别

    Statement和PreparedStatement之间的区别: 1.PreparedStatement是预编译的,对于批量处理可以大大提高效率. 也叫JDBC存储过程2.使用 Statement ...