AT1984 Wide Swap

题意翻译

给出一个元素集合为\(\{1,2,\dots,N\}(1\leq N\leq 500,000)\)的排列\(P\),当有\(i,j(1\leq i<j\leq N)\)满足\(j-i\geq K\)\((1\leq K\leq N-1)\)且\(|P_{i}-P{j}|=1\)时,可以交换\(P_{i}\)和\(P_{j}\)

求:可能排列中字典序最小的排列

输入格式:

\(N\) \(K\)

\(P_{1}\) \(P_{2}\) \(\dots\) \(P_{N}\)


这题目真是好思路啊。

首先,一个元素有两个属性,称为权值\(p\)和位置\(l\),交换的过程可以定义为固定权值交换位置,或者固定位置交换权值。

发现原本题目中的条件不好操作,于是把权值和位置交换意义,那么问题就变成了:

让权值较小的尽可能呆在前面,当两个元素相邻并且权值之差不小于\(k\)时,可以交换这两个权值的位置。

我们把权值当成固有属性,拿位置去交换,那么如果两个元素的权值之差小于\(k\),那么它们的相对位置是不会改变的,我们对这一对按原有位置连一条有向边。

对整个图都这么连,然后以\(\tt{topo}\)序为第一关键字,权值为第二关键字跑优先队列\(\tt{topo}\)排序,就可以找到转换以后的字典序了。

但是发现这样连边是\(O(n^2)\)的,过不了这个题,得想办法优化一下连边。

考虑一个点\(i\)会向之后的哪些点连边,\(\tt{Ta}\)会连接权值在\([p_i-k+1,p_i+k-1]\)内的所有边,而\(k\)是不变的。所以我们只需要连接\(\tt{Ta}\)位置上第一个大于\(\tt{Ta}\)和第一个小于\(\tt{Ta}\)的边就可以了,其余的这两个点会连上。

发现可以用线段树维护,倒序加点,对权值建树,区间查询最小位置。

复杂度:\(O(nlogn)\)


Code:

#include <cstdio>
#include <cstring>
#include <queue>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define dep(i,a,b) for(int i=a;i>=b;i--)
#define lb(a) lower_bound(a)
#define is(a) insert(a)
#define ps(a) push(a)
const int N=5e5+10;
const int inf=0x3f3f3f3f;
int in[N],loc[N],p[N],ans[N],tot,n,k;
std::priority_queue <int,std::vector<int>,std::greater<int> > q;
int head[N],to[N<<1],Next[N<<1],cnt;
void add(int u,int v)
{to[++cnt]=v,Next[cnt]=head[u],head[u]=cnt;
}
#define ls id<<1
#define rs id<<1|1
int min(int x,int y){return x<y?x:y;}
int max(int x,int y){return x>y?x:y;}
int mi[N<<2];
void change(int id,int l,int r,int p,int d)
{if(l==r) {mi[id]=d;return;}int mid=l+r>>1;if(p<=mid) change(ls,l,mid,p,d);else change(rs,mid+1,r,p,d);mi[id]=min(mi[ls],mi[rs]);
}
int query(int id,int L,int R,int l,int r)
{if(mi[id]==inf) return inf;if(l==L&&r==R) return mi[id];int Mid=L+R>>1;if(r<=Mid) return query(ls,L,Mid,l,r);else if(l>Mid) return query(rs,Mid+1,R,l,r);else return min(query(ls,L,Mid,l,Mid),query(rs,Mid+1,R,Mid+1,r));
}
int main()
{scanf("%d%d",&n,&k);rep(i,1,n) scanf("%d",p),p[p[0]]=i;memset(mi,0x3f,sizeof(mi));dep(i,n,1){int loc=query(1,1,n,p[i],min(n,p[i]+k-1));if(loc!=inf) add(p[i],p[loc]),++in[p[loc]];loc=query(1,1,n,max(1,p[i]-k+1),p[i]);if(loc!=inf) add(p[i],p[loc]),++in[p[loc]];change(1,1,n,p[i],i);}rep(i,1,n) if(!in[i]) q.ps(i);while(!q.empty()){int now=q.top();ans[now]=++tot;q.pop();for(int i=head[now];i;i=Next[i]){int v=to[i];--in[v];if(!in[v]) q.ps(v);}}rep(i,1,n) printf("%d\n",ans[i]);return 0;
}

2018.10.26

转载于:https://www.cnblogs.com/butterflydew/p/9854320.html

AT1984 Wide Swap相关推荐

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

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

  2. AGC001 补题小结

    Problem A BBQ Easy 简要题意:给定 \(2n\) 个数字,两两配对,一对的贡献为它们的 \(min\) ,求最大贡献和.\(n\le 100\) tag:小学生贪心 题解:排个序,求 ...

  3. 【CAS】Implementing generic double-word compare and swap for x86/x86-64

    Written by Marwan Burelle 2013-02-27 10:10:00 目录 The ABA problem Double-word CAS Using cmpxchg for 3 ...

  4. List元素互换,List元素转换下标,Java Collections.swap()方法实例解析

    Java Collections.swap()方法解析 jdk源码: public static void swap(List<?> list, int i, int j) {// ins ...

  5. Wide Deep的OneFlow网络训练

    Wide & Deep的OneFlow网络训练 HugeCTR是英伟达提供的一种高效的GPU框架,专为点击率(CTR)估计训练而设计. OneFlow对标HugeCTR搭建了Wide & ...

  6. 管理员技术(六): 硬盘分区及格式化、 新建一个逻辑卷、调整现有磁盘的分区、扩展逻辑卷的大小、添加一个swap分区...

    一.硬盘分区及格式化 问题: 本例要求熟悉硬盘分区结构,使用fdisk分区工具在磁盘 /dev/vdb 上按以下要求建立分区: 1> 采用默认的 msdos 分区模式         2> ...

  7. [HDOJ2819]Swap(二分图最大匹配, 匈牙利算法)

    题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=2819 题意:给一张n*n的01矩阵,可以任意交换其中的行或者列,问是否可以交换出来一个对角 ...

  8. 手动新增swap分区

    1.建立1G的交换分区(填充) #dd  if =/dev/zore of =/opt/swapfile bs=1M count=1024 2.设置交换分区文件 #mkswap /opt/swapfi ...

  9. (C++)用指针实现两数交换函数swap()的两种方法

    #include<cstdio>//用指针写swap()函数 void swap_1(int* p1,int* p2){int temp = *p1;*p1 = *p2;*p2 = tem ...

最新文章

  1. 国内拉取google Kubernetes镜像
  2. rs485调试软件_【乐创“芯”说】你想知道的RS485
  3. 浅析Objective-C字面量
  4. Ajax异步请求-简单模版
  5. chapter 2 自定义数据类型
  6. java中CyclicBarrier的使用
  7. ASP.NET 2.0 中的 DataSource 系列控件
  8. 【MySQL】redo log --- 刷入磁盘过程
  9. nginx php.ini配置_Nginx下修改php.ini后重新加载配置文件命令
  10. php修改音频文件_php获取mp3文件信息时长修改
  11. 基于RTP协议的数据通讯程序
  12. 好用的import: Vite的Glob 导入
  13. AudFree Tidable Music Converter for Mac - 音乐格式转换软件
  14. 精通SQL的30张简图
  15. SpringBoot实现导入功能
  16. delphi android 微信支付,Delphi XE10实现移动端微信支付接口(含源码)
  17. 随机生成一注双色球号码
  18. 介绍一款在线仿站小工具
  19. Iometer存储测试工具参数说明-5 存储规格选项
  20. Mysql中从零点到当前时刻的SQL判断

热门文章

  1. python 收发邮件_python发送各类邮件的主要基本方法
  2. GStreamer基础教程07 - 播放速率控制
  3. 测试sql语句的执行效率
  4. 关于css 的AST 语法树的理解
  5. MFC版链表实现稀疏多项式相加减
  6. [课程相关]homework-06
  7. C++ primer 笔记(二)
  8. Proxy server 緩存 jsp html
  9. android记事本项目案例,Android实现记事本项目完整实例源代码
  10. php 识别语种,HYPHP增加多国语言支持 PHP通过用户浏览器判断来源国家方案