题目链接: https://atcoder.jp/contests/agc001/tasks/agc001_f

题解: 先变成排列的逆,要求\(1\)的位置最小,其次\(2\)的位置最小,依次排下去(称之为逆字典序)。有一些条件,如果两数\(x,y\)的差小于\(K\), 那么它们的相对位置不可变。

所以如果从必须在前面的往必须在后面的连边,得到的图将是一个DAG,现在需要求它的一个拓扑序满足上面的最优化条件。

先排除几个错误结论: 翻转后字典序越大,字典序越小,错误。逆字典序越大,字典序越大/越小,错误。

有这样一个正确结论: 逆字典序最小的拓扑序即为翻转后字典序最大的拓扑序。注意必须是在一个图的拓扑序的集合中,不可拓展到任意排列的集合中,而且是“最大”“最小”,不可拓展为“越大”“越小”。

对于这个结论,网上好多感性理解/证明都是明显有问题的。我给出一个我自己的证明: (可能有错,有错请指出) 考虑归纳,假设往图里添加一个新的点\(n\), 假设在翻转后字典序最大的拓扑序里\(n\)的位置为\(k\), 那么\(n\)一定要向位置\((k+1)\)上的数连边(否则交换它们会使得翻转后字典序更大),即\(n\)现在所处的位置是合法情况下其所处的最靠后的位置。又因为在没加\(n\)之前该排列是逆字典序最小的,因此加了\(n\)之后会使得后面最小个数的小于\(n\)的数位置后移\(1\), 因此加了之后依然是最小。

所以我们只需要建出图来求翻转后字典序最小的拓扑序,然而边数是\(O(n^2)\)的,但是发现连边时只需要考虑区间内最小的和最大的即可。线段树优化。

时间复杂度\(O(n\log n)\)

代码

  1. #include<cstdio>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<utility>
  5. #include<algorithm>
  6. #include<queue>
  7. #define llong long long
  8. using namespace std;
  9. const int N = 5e5;
  10. struct SegmentTree
  11. {
  12. struct SgTNode
  13. {
  14. int val;
  15. } sgt[(N<<2)+2];
  16. void pushup(int pos) {sgt[pos].val = max(sgt[pos<<1].val,sgt[pos<<1|1].val);}
  17. void modify(int pos,int le,int ri,int lrb,int val)
  18. {
  19. if(le==lrb && ri==lrb) {sgt[pos].val = val; return;}
  20. int mid = (le+ri)>>1;
  21. if(lrb<=mid) {modify(pos<<1,le,mid,lrb,val);}
  22. else if(lrb>mid) {modify(pos<<1|1,mid+1,ri,lrb,val);}
  23. pushup(pos);
  24. }
  25. int querymax(int pos,int le,int ri,int lb,int rb)
  26. {
  27. if(lb<=le && rb>=ri) {return sgt[pos].val;}
  28. int mid = (le+ri)>>1;
  29. int ret = 0;
  30. if(rb>mid) {ret = max(ret,querymax(pos<<1|1,mid+1,ri,lb,rb));}
  31. if(lb<=mid) {ret = max(ret,querymax(pos<<1,le,mid,lb,rb));}
  32. return ret;
  33. }
  34. } smt;
  35. struct Edge
  36. {
  37. int v,nxt;
  38. } e[(N<<1)+2];
  39. int a[N+3];
  40. int b[N+3];
  41. int ind[N+3];
  42. int fe[N+3];
  43. priority_queue<pair<int,int> > pq;
  44. pair<int,int> ans[N+3];
  45. int fans[N+3];
  46. int n,m,en;
  47. void addedge(int u,int v)
  48. {
  49. // printf("addedge%d %d\n",u,v);
  50. en++; e[en].v = v; ind[v]++;
  51. e[en].nxt = fe[u]; fe[u] = en;
  52. }
  53. int main()
  54. {
  55. scanf("%d%d",&n,&m);
  56. for(int i=1; i<=n; i++) {int x; scanf("%d",&b[i]); a[b[i]] = i;}
  57. for(int i=1; i<=n; i++)
  58. {
  59. ans[i].second = a[i];
  60. int x = smt.querymax(1,0,n,max(a[i]-m+1,0),a[i]);
  61. int y = smt.querymax(1,0,n,a[i],min(a[i]+m-1,n));
  62. if(x) {addedge(i,x);}
  63. if(y) {addedge(i,y);}
  64. // printf("iquery %d %d %d\n",i,max(0,a[i]-m+1),min(n,a[i]+m-1));
  65. // printf("imodify %d %d %d\n",i,ans[i].second,ans[i].first);
  66. smt.modify(1,0,n,ans[i].second,i);
  67. // printf("ans%d %d %d\n",i,ans[i].first,ans[i].second);
  68. }
  69. for(int i=1; i<=n; i++) if(ind[i]==0) {pq.push(make_pair(a[i],i));}
  70. int j = 0;
  71. while(!pq.empty())
  72. {
  73. pair<int,int> tmp = pq.top(); pq.pop();
  74. j++; b[j] = tmp.first; int u = tmp.second;
  75. for(int i=fe[u]; i; i=e[i].nxt)
  76. {
  77. ind[e[i].v]--;
  78. if(ind[e[i].v]==0)
  79. {
  80. pq.push(make_pair(a[e[i].v],e[i].v));
  81. }
  82. }
  83. }
  84. for(int i=1; i<n+1-i; i++) swap(b[i],b[n+1-i]);
  85. for(int i=1; i<=n; i++) fans[b[i]] = i;
  86. for(int i=1; i<=n; i++) printf("%d\n",fans[i]);
  87. return 0;
  88. }

AtCoder AGC001F Wide Swap (线段树、拓扑排序)的更多相关文章

  1. 【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 ...

  2. BZOJ4383 Pustynia(线段树+拓扑排序)

    线段树优化建图暴力拓扑排序即可.对于已确定的数,拓扑排序时dp,每个节点都尽量取最大值,如果仍与已确定值矛盾则无解.叶子连出的边表示大于号,其余边表示大于等于. #include<iostrea ...

  3. hdu 5195 DZY Loves Topological Sorting 线段树+拓扑排序

    DZY Loves Topological Sorting Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/sho ...

  4. HDU5638 / BestCoder Round #74 (div.1) 1003 Toposort 线段树+拓扑排序

    Toposort   问题描述 给出nn个点mm条边的有向无环图. 要求删掉恰好kk条边使得字典序最小的拓扑序列尽可能小. 输入描述 输入包含多组数据. 第一行有一个整数TT, 表示测试数据组数. 对 ...

  5. [CSP-S模拟测试]:Permutation(线段树+拓扑排序+贪心)

    题目描述 你有一个长度为$n$的排列$P$与一个正整数$K$你可以进行如下操作若干次使得排列的字典序尽量小对于两个满足$|i−j|\geqslant K$且$|P_i−P_j|=1$的下标$i$与$j ...

  6. BZOJ3832[Poi2014]Rally——权值线段树+拓扑排序

    题目描述 An annual bicycle rally will soon begin in Byteburg. The bikers of Byteburg are natural long di ...

  7. BZOJ_3012_[Usaco2012 Dec]First!_trie树+拓扑排序

    BZOJ_3012_[Usaco2012 Dec]First!_trie树+拓扑排序 题意: 给定n个总长不超过m的互不相同的字符串,现在你可以任意指定字符之间的大小关系.问有多少个串可能成为字典序最 ...

  8. bzoj3276磁力 两种要求下的最大值:分块or线段树+拓扑

    进阶指南上的做法是分块的.. 但是线段树搞起来也挺快,将磁石按照距离排序,建立线段树,结点维护区间质量最小值的下标 进行拓扑,每次在可行的范围内在线段树中找到质量最小的下标取出,取出后再将线段树对应的 ...

  9. Codeforces 588E. A Simple Task (线段树+计数排序思想)

    题目链接:http://codeforces.com/contest/558/problem/E 题意:有一串字符串,有两个操作:1操作是将l到r的字符串升序排序,0操作是降序排序. 题解:建立26棵 ...

随机推荐

  1. [转帖]X86_64平台上利用qemu安装aarch64架构的虚拟机

    X86_64平台上利用qemu安装aarch64架构的虚拟机 https://blog.csdn.net/chenxiangneu/article/details/78955462 遇到原作者一样的问 ...

  2. Hive开发中使用变量的两种方法

    在使用hive开发数据分析代码时,经常会遇到需要改变运行参数的情况,比如select语句中对日期字段值的设定,可能不同时间想要看不同日期的数据,这就需要能动态改变日期的值.如果开发量较大.参数多的话, ...

  3. 模板渲染JinJa2

    模板渲染JinJa2 ​ 可以从数据库中查询数据,然后去替换我html中的对应内容(专业名词叫做模板渲染,你先渲染一下,再给浏览器进行渲染),然后再发送给浏览器完成渲染. 这个过程就相当于HTML模板 ...

  4. 学习WCF之路,长期更新

    我学习WCF之路:创建一个简单的WCF程序   为了使读者对基于WCF的编程模型有一个直观的映像,我将带领读者一步一步地创建一个完整的WCF应用.本应用功能虽然简单,但它涵盖了一个完整WCF应用的基本 ...

  5. Jquery复习(一)之animate()易忘点

    可以用 animate() 方法来操作所有 CSS 属性吗? 是的,几乎可以!不过,需要记住一件重要的事情:当使用 animate() 时,必须使用 Camel 标记法书写所有的属性名,比如,必须使用 ...

  6. 可以提升幸福感的js小技巧(下)

    4.数字 4.1 不同进制表示法 ES6中新增了不同进制的书写格式,在后台传参的时候要注意这一点. 29 // 10进制 035 // 8进制29 原来的方式 0o35 // 8进制29 ES6的方式 ...

  7. ajax跨域jsonp —— javascript

    目录 jsonp是什么 jsonp原理 原生js使用jsonp jquery使用jsonp jsonp是什么 jsonp作用:解决跨域问题 为什么有跨域问题? “同源策略限制了从同一个源加载的文档或脚 ...

  8. 【maven】IDEA:存在jar包,pom.xml文件没报错,但是Maven-Project-Dependencies有红线报错

    1.这个问题很简单 把pom.xml里这些出错的jar包的引用先删除,再刷新一次,再添上,就行了 2.大概是idea有点反应迟钝

  9. poj 1543 Perfect Cubes (暴搜)

    Perfect Cubes Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 15302   Accepted: 7936 De ...

  10. 引用vector里的元素被删除后,引用会怎么样?

    引用的定义不多说,直接看做变量的别名就可以了.有一天写着写着代码,突然想到,如果对vector里某个元素设置引用后,将这个元素从vector里删除会怎么样?我思考了下,认为那个元素会被删除,但是引用还 ...