参考ExtremeSpanningTrees,考虑优化整体二分时求$g_{i}\in \{w_{mid},w_{mid+1}\}$的最优解

首先题目有一个条件似乎没有写出来,是保证$l\le k\le r$的(但并不是特别重要,可能更方便)

可以发现只关心于$k$属于当前考虑的点集中的询问即可,因此每一次层的限制数为$o(m)$(可以通过上面的条件,将区间求并后优化为$o(n)$个)

考虑用线段树来优化建图,具体来说,分为以下几步:

1.将点以及区间离散到点个数长度的区间,来保证复杂度;

2.建两颗线段树,左边的线段树从儿子到父亲,右边的线段树从父亲到儿子(流量inf)

3.每一个点连向左边对应的叶子,右边的叶子连向对应的点,根据权值划分到$S$和$T$

4.对于初始$k$到$[l,r]$的边,对应为$k$在左边的叶子连向右边$[l,r]$对应的log个区间,反之类似

理论时间复杂度为$o(n^{3}\log^{2}n)$,可以通过

  1. 1 #include<bits/stdc++.h>
  2. 2 using namespace std;
  3. 3 #define N 5005
  4. 4 #define ll long long
  5. 5 #define oo 0x3f3f3f3f
  6. 6 #define vi vector<int>
  7. 7 #define L (k<<1)
  8. 8 #define R (L+1)
  9. 9 struct ji{
  10. 10 int nex,to,len;
  11. 11 }edge[N<<5];
  12. 12 queue<int>q;
  13. 13 int n,m,p,l,r,k,lx[N][2],rx[N][2],w[N],v[N],a[N],ans[N];
  14. 14 int V,E,leaf[N],head[N<<4],work[N<<4],d[N<<4],vis[N<<4],bl[N];
  15. 15 bool cmp(int x,int y){
  16. 16 return (bl[x]<bl[y])||(bl[x]==bl[y])&&(x<y);
  17. 17 }
  18. 18 void add(int x,int y,int z){
  19. 19 edge[E].nex=head[x];
  20. 20 edge[E].to=y;
  21. 21 edge[E].len=z;
  22. 22 head[x]=E++;
  23. 23 if (E&1)add(y,x,0);
  24. 24 }
  25. 25 bool bfs(){
  26. 26 memset(d,oo,sizeof(d));
  27. 27 d[0]=0;
  28. 28 q.push(0);
  29. 29 while (!q.empty()){
  30. 30 int k=q.front();
  31. 31 q.pop();
  32. 32 for(int i=head[k];i!=-1;i=edge[i].nex)
  33. 33 if ((edge[i].len)&&(d[edge[i].to]==oo)){
  34. 34 d[edge[i].to]=d[k]+1;
  35. 35 q.push(edge[i].to);
  36. 36 }
  37. 37 }
  38. 38 return d[(V<<1)+n+1]<oo;
  39. 39 }
  40. 40 int dfs(int k,int s){
  41. 41 if (k>(V<<1)+n)return s;
  42. 42 for(int &i=work[k];i!=-1;i=edge[i].nex)
  43. 43 if ((edge[i].len)&&(d[edge[i].to]==d[k]+1)){
  44. 44 int p=dfs(edge[i].to,min(s,edge[i].len));
  45. 45 if (p){
  46. 46 edge[i].len-=p;
  47. 47 edge[i^1].len+=p;
  48. 48 return p;
  49. 49 }
  50. 50 }
  51. 51 return 0;
  52. 52 }
  53. 53 void dinic(){
  54. 54 while (bfs()){
  55. 55 memcpy(work,head,sizeof(work));
  56. 56 while (dfs(0,oo));
  57. 57 }
  58. 58 }
  59. 59 void dfs(int k){
  60. 60 if (vis[k])return;
  61. 61 vis[k]=1;
  62. 62 for(int i=head[k];i!=-1;i=edge[i].nex)
  63. 63 if (edge[i].len)dfs(edge[i].to);
  64. 64 }
  65. 65 void build(int k,int l,int r){
  66. 66 if (l==r){
  67. 67 leaf[l]=k;
  68. 68 V=max(V,k);
  69. 69 return;
  70. 70 }
  71. 71 int mid=(l+r>>1);
  72. 72 build(L,l,mid);
  73. 73 build(R,mid+1,r);
  74. 74 }
  75. 75 void update(int k,int l,int r,int x,int y,int z,int p){
  76. 76 if ((l>y)||(x>r))return;
  77. 77 if ((x<=l)&&(r<=y)){
  78. 78 if (p)add(k,z+V,oo);
  79. 79 else add(z,k+V,oo);
  80. 80 return;
  81. 81 }
  82. 82 int mid=(l+r>>1);
  83. 83 update(L,l,mid,x,y,z,p);
  84. 84 update(R,mid+1,r,x,y,z,p);
  85. 85 }
  86. 86 void dfs(int l,int r,int x,int y){
  87. 87 if (x==y){
  88. 88 for(int i=l;i<=r;i++)ans[a[i]]=v[x];
  89. 89 return;
  90. 90 }
  91. 91 int mid=(x+y>>1);
  92. 92 V=E=0;
  93. 93 build(1,1,r-l+1);
  94. 94 for(int i=0;i<=(V<<1)+n+1;i++)head[i]=-1;
  95. 95 for(int i=2;i<=V;i++){
  96. 96 add(i,i/2,oo);
  97. 97 add(i/2+V,i+V,oo);
  98. 98 }
  99. 99 for(int i=l;i<=r;i++){//若i比j小则i向j连边,源点连大的,汇点连小的
  100. 100 add((V<<1)+i,leaf[i-l+1],oo);
  101. 101 add(leaf[i-l+1]+V,(V<<1)+i,oo);
  102. 102 if (w[a[i]]>=v[mid+1])add(0,(V<<1)+i,1);
  103. 103 else add((V<<1)+i,(V<<1)+n+1,1);
  104. 104 }
  105. 105 for(int i=l;i<=r;i++)
  106. 106 for(int j=0;j<2;j++){
  107. 107 int x=lx[a[i]][j],y=rx[a[i]][j];
  108. 108 int wx=lower_bound(a+l,a+r+1,x)-a-l+1,wy=upper_bound(a+l,a+r+1,y)-a-l;
  109. 109 if (wx<wy)update(1,1,r-l+1,wx,wy,leaf[i-l+1],j);
  110. 110 }
  111. 111 dinic();
  112. 112 for(int i=0;i<=(V<<1)+n+1;i++)vis[i]=0;
  113. 113 dfs(0);
  114. 114 for(int i=l;i<=r;i++){
  115. 115 if ((w[a[i]]>=v[mid+1])&&(vis[leaf[i-l+1]])||(w[a[i]]<v[mid+1])&&(vis[leaf[i-l+1]+V]))bl[a[i]]=1;
  116. 116 else bl[a[i]]=0;
  117. 117 }
  118. 118 sort(a+l,a+r+1,cmp);
  119. 119 for(int i=l;i<=r+1;i++){
  120. 120 if ((bl[a[i]])||(i>r)){
  121. 121 if (l<i)dfs(l,i-1,x,mid);
  122. 122 if (i<=r)dfs(i,r,mid+1,y);
  123. 123 return;
  124. 124 }
  125. 125 }
  126. 126 }
  127. 127 int main(){
  128. 128 scanf("%d%d",&n,&m);
  129. 129 for(int i=1;i<=n;i++)scanf("%d",&w[i]);
  130. 130 for(int i=1;i<=n;i++)
  131. 131 for(int j=0;j<2;j++)lx[i][j]=rx[i][j]=i;
  132. 132 for(int i=1;i<=m;i++){
  133. 133 scanf("%d%d%d%d",&p,&l,&r,&k);
  134. 134 lx[k][p]=min(lx[k][p],l);
  135. 135 rx[k][p]=max(rx[k][p],r);
  136. 136 }
  137. 137 memcpy(v,w,sizeof(v));
  138. 138 sort(v+1,v+n+1);
  139. 139 int nn=unique(v+1,v+n+1)-v-1;
  140. 140 for(int i=1;i<=n;i++)a[i]=i;
  141. 141 dfs(1,n,1,nn);
  142. 142 long long sum=0;
  143. 143 for(int i=1;i<=n;i++)sum+=abs(ans[i]-w[i]);
  144. 144 for(int i=1;i<=n;i++){
  145. 145 for(int j=lx[i][0];j<=rx[i][0];j++)assert(ans[j]>=ans[i]);
  146. 146 for(int j=lx[i][1];j<=rx[i][1];j++)assert(ans[j]<=ans[i]);
  147. 147 }
  148. 148 printf("%lld",sum);
  149. 149 }

[loj6518]序列的更多相关文章

  1. 【夯实PHP基础】UML序列图总结

    原文地址 序列图主要用于展示对象之间交互的顺序. 序列图将交互关系表示为一个二维图.纵向是时间轴,时间沿竖线向下延伸.横向轴代表了在协作中各独立对象的类元角色.类元角色用生命线表示.当对象存在时,角色 ...

  2. Windows10-UWP中设备序列显示不同XAML的三种方式[3]

    阅读目录: 概述 DeviceFamily-Type文件夹 DeviceFamily-Type扩展 InitializeComponent重载 结论 概述 Windows10-UWP(Universa ...

  3. 软件工程里的UML序列图的概念和总结

    俗话说,自己写的代码,6个月后也是别人的代码……复习!复习!复习! 软件工程的一般开发过程:愿景分析.业务建模,需求分析,健壮性设计,关键设计,最终设计,实现…… 时序图也叫序列图(交互图),属于软件 ...

  4. python序列,字典备忘

    初识python备忘: 序列:列表,字符串,元组len(d),d[id],del d[id],data in d函数:cmp(x,y),len(seq),list(seq)根据字符串创建列表,max( ...

  5. BZOJ 1251: 序列终结者 [splay]

    1251: 序列终结者 Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 3778  Solved: 1583[Submit][Status][Discu ...

  6. 最长不下降序列nlogn算法

    显然n方算法在比赛中是没有什么用的(不会这么容易就过的),所以nlogn的算法尤为重要. 分析: 开2个数组,一个a记原数,f[k]表示长度为f的不下降子序列末尾元素的最小值,tot表示当前已知的最长 ...

  7. [LeetCode] Sequence Reconstruction 序列重建

    Check whether the original sequence org can be uniquely reconstructed from the sequences in seqs. Th ...

  8. [LeetCode] Binary Tree Longest Consecutive Sequence 二叉树最长连续序列

    Given a binary tree, find the length of the longest consecutive sequence path. The path refers to an ...

  9. [LeetCode] Repeated DNA Sequences 求重复的DNA序列

    All DNA is composed of a series of nucleotides abbreviated as A, C, G, and T, for example: "ACG ...

随机推荐

  1. 统计学习:线性支持向量机(SVM)

    学习策略 软间隔最大化 上一章我们所定义的"线性可分支持向量机"要求训练数据是线性可分的.然而在实际中,训练数据往往包括异常值(outlier),故而常是线性不可分的.这就要求我们 ...

  2. Java(13)详解构造方法

    作者:季沐测试笔记 原文地址:https://www.cnblogs.com/testero/p/15201600.html 博客主页:https://www.cnblogs.com/testero ...

  3. Upload-labs通关指南(下) 11-20

    承接上篇,这次我们继续做下半部分. 有些题目有其他做法是针对于windows系统特性的,并不能在linux上奏效,因此不在考虑范围之内. Pass-11 制作图片马直接上传 copy a.jpg /a ...

  4. BPMN 學習實例

    什麼是業務流程圖? What is BPMN 業務流程建模符號(BPMN)是業務流程建模的一種方法.它基於統一建模語言(UML)中活動圖的概念,以圖形符號(業務流程圖)支持業務流程的規範.BPMN為企 ...

  5. Charles的简单用法

    Charles的简单用法 一.抓电脑上 http 包 二.显示请求的 Request 和 Response 三.抓取电脑上 https 包 1.安装根证书 2.在钥匙串中启用根证书 3.配置哪些需要抓 ...

  6. Java-基础-LinkedList

    1. 简介 LinkedList 同时实现了List和Deque接口,也就是说它既可以看作是一个顺序容器,又可以看作是双向队列. 既然是双向列表,那么它的每个数据节点都一定有两个指针,分别指向它的前驱 ...

  7. 单片机STM32的5个时钟源知识

    众所周知STM32有5个时钟源HSI.HSE.LSI.LSE.PLL,其实他只有四个,因为从上图中可以看到PLL都是由HSI或HSE提供的. 其中,高速时钟(HSE和HSI)提供给芯片主体的主时钟.低 ...

  8. VIVADO 2017.4配置MIG IP注意事项

    1.2GB的single rank SODIMMs配置pin还是和以前一样没有问题: 2.8GB SODIMMs配置pin需要注意4点: (1).所有的DDR3引脚都需要在连续的BANK上,例如Z71 ...

  9. 滑动窗口的最大值 牛客网 剑指Offer

    滑动窗口的最大值 牛客网 剑指Offer 题目描述 给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值.例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6 ...

  10. Python 语法错误 except Exception, e: ^ SyntaxError: invalid syntax

    出这个问题是因为python2和python3 语法有些不同 python2 和 3 处理 except 子句的语法有点不同,需要注意: Python2 try: print ("hello ...