(四边形不等式的套路题)

对于某一组$a_{i}$,显然可以区间dp,设$f_{l,r}$表示区间$[l,r]$​的答案,则转移即
$$
f_{l,r}=\begin{cases}0&(l=r)\\\sum_{i=l}^{r}\sum_{j=l}^{r}dist(a_{i},a_{j})+\min_{l\le i<r}(f_{l,i}+f_{i+1,r})&(l<r)\end{cases}
$$
为了方便,对于$l<r$定义$f_{l,r}$的最优决策为后者取到$\min$时的(任意一个)$i$

记$S_{l,r}=\sum_{i=l}^{r}\sum_{j=l}^{r}dist(a_{i},a_{j})$,不难发现其满足单调性四和边形不等式,即
$$
\forall a_{1}\le a_{2}\le b_{1}\le b_{2},\begin{cases}S_{a_{2},b_{1}}\le S_{a_{1},b_{2}}\\S_{a_{1},b_{1}}+S_{a_{2},b_{2}}\le S_{a_{1},b_{2}}+S_{a_{2},b_{1}}\end{cases}
$$
由此,我们就可以得到$f$满足四边形不等式,证明如下——

引理1:$f$满足四边形不等式当且仅当$\forall a<b,f_{a,b}+f_{a+1,b+1}\le f_{a,b+1}+f_{a+1,b}$

若$a+1<b$,即有$f_{a+1,b}+f_{a+2,b+1}\le f_{a+1,b+1}+f_{a+2,b}$

将两式相加,消项后即有$f_{a,b}+f_{a+2,b+1}\le f_{a,b+1}+f_{a+2,b}$

不难发现记将$a+1$变为了$a+2$,以此类推即有$f_{a_{1},b}+f_{a_{2},b+1}\le f_{a_{1},b+1}+f_{a_{2},b}$

类似地,也可以将$b+1$变为$b+2$,以此类推即得到四边形不等式

另外,对于$a_{1}=a_{2}$或$b_{1}=b_{2}$的情况,四边形不等式显然成立

此时即只有两维,对$b-a$归纳,在$b-a\le 2$时简单分析显然成立

若$b-a<k$时成立,考虑$b-a=k$时:

设$f_{a,b+1}$的最优决策为$x$,$f_{a+1,b}$的最优决策为$y$,不妨假设$x\le y$(对于$x>y$​是类似地),即有
$$
f_{a,b+1}+f_{a+1,b}=(f_{a,x}+f_{x+1,b+1}+S_{a,b+1})+(f_{a+1,y}+f_{y+1,b}+S_{a+1,b})
$$
而对于$f_{a,b}$和$f_{a+1,b+1}$,显然该处决策也对其取$\min$​,即有
$$
f_{a,b}+f_{a+1,b+1}\le (f_{a,x}+f_{x+1,b}+S_{a,b})+(f_{a+1,y}+f_{y+1,b+1}+S_{a+1,b+1})
$$
将两者比较,消掉相同项以及$S$​的四项(对应其四边形不等式),即求证
$$
f_{x+1,b+1}+f_{y+1,b}\le f_{x+1,b}+f_{y+1,b+1}
$$
不难发现这也即为四边形不等式,由归纳显然成立

综上,即证明了$f$满足四边形不等式

引理2:若$f$满足四边形不等式,则$f$具有决策单调性

首先,来解释一下此处的"决策单调性":令$g_{l,r}$为$[l,r]$处的最优决策,则$g_{l,r-1}\le g_{l,r}\le g_{l+1,r}$

不妨考虑$g_{l,r-1}\le g_{l,r}$(对于$g_{l,r}\le g_{l+1,r}$是类似地),令$j=g_{l,r-1}$,也即求证$\forall l\le i<j$(对于$f_{l,r}$)在i处转移不如在$j$处转移,显然由此即可得到$j\le g_{l,r}$

具体的,已知$f_{l,j}+f_{j+1,r-1}\le f_{l,i}+f_{i+1,r-1}$,构造$f_{i+1,r-1}+f_{j+1,r}\le f_{i+1,r}+f_{j+1,r-1}$(根据f的四边形不等式),将两者相加即$f_{l,j}+f_{j+1,r}\le f_{l,i}+f_{i+1,r}$,也即所求证

由此,枚举的范围变为$[g_{l,r-1},g_{l+1,r}]$,将长度求和即$\sum_{l=1}^{n}\sum_{r=l+1}^{n}(g_{l+1,r}-g_{l,r-1})\le \sum_{l=1}^{n}g_{l,n}$,后者显然为$o(n^{2})$,也即可$o(n^{2})$求出初始$a_{i}$的dp数组

下面,考虑如何修改:假设加入元素后序列长度为$n$,相比原来要额外求出的即$\forall 1\le i\le n,f_{i,n}$,显然其仍满足$g_{i,n-1}\le g_{i,n}\le g_{i+1,n}$,但此时长度求和后并不能相消,由于均摊会使得其退化到$o(rn^{2})$

下面,考虑更严格的单调性——若对于$l\le x<y<r$对$f_{l,r}$在$x$处不如$y$处,则对$f_{l-1,r}$在$x$处也不如$y$处

(事实上,满足决策单调性的通常都满足此性质)

由此,从后往前处理出$g_{i,n}$(被划分为若干个区间),并通过二分来求出当前加入位置的影响即可

综上,总复杂度为$o(m^{2}+n^{2}+rn\log n)$,可以通过

  1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 2005
4 #define M 305
5 #define ll long long
6 struct Edge{
7 int nex,to,len;
8 }edge[N<<1];
9 deque<int>Q;
10 int t,n,q,E,x,y,head[N],l[M],a[M][N],pos[M][N],L[N],R[N],g[N][N];
11 ll d[N][N],S1[N][N],S2[M][N],f[N][N],F[M][N];
12 void add(int x,int y,int z){
13 edge[E]=Edge{head[x],y,z};
14 head[x]=E++;
15 }
16 void dfs(int k,int fa,ll s,int st){
17 d[st][k]=s;
18 for(int i=head[k];i!=-1;i=edge[i].nex)
19 if (edge[i].to!=fa)dfs(edge[i].to,k,s+edge[i].len,st);
20 }
21 ll get_S(int i,int x,int y){
22 if (x>y)return 0;
23 if (y<=l[0])return S1[x][y];
24 return S2[pos[i][y]][x];
25 }
26 ll get_f(int i,int x,int y){
27 if (y<=l[0])return f[x][y];
28 return F[pos[i][y]][x];
29 }
30 ll calc(int i,int j,int k){
31 if (j>=k)return 1e18;
32 return get_f(i,j,k-1)+F[i][k]+S2[i][j];
33 }
34 int main(){
35 scanf("%d",&t);
36 while (t--){
37 scanf("%d%d%d",&n,&l[0],&q);
38 E=0;
39 memset(head,-1,sizeof(head));
40 for(int i=1;i<=n;i++){
41 scanf("%d%d",&x,&y);
42 add(x,i,y),add(i,x,y);
43 }
44 for(int i=0;i<=n;i++)dfs(i,-1,0,i);
45 for(int i=1;i<=l[0];i++)scanf("%d",&a[0][i]);
46 for(int i=1;i<=l[0];i++)S1[i][i]=f[i][i]=0;
47 for(int i=l[0];i;i--){
48 ll s=0;
49 for(int j=i+1;j<=l[0];j++){
50 s+=d[a[0][i]][a[0][j]];
51 S1[i][j]=S1[i+1][j]+s;
52 if (i+1==j){
53 g[i][j]=i;
54 f[i][j]=S1[i][j];
55 }
56 else{
57 f[i][j]=1e18;
58 for(int k=g[i][j-1];k<=g[i+1][j];k++)
59 if (f[i][k]+f[k+1][j]+S1[i][j]<f[i][j]){
60 g[i][j]=k;
61 f[i][j]=f[i][k]+f[k+1][j]+S1[i][j];
62 }
63 }
64 }
65 }
66 printf("%lld\n",(f[1][l[0]]<<1));
67 for(int i=1;i<=q;i++){
68 scanf("%d%d",&x,&y);
69 l[i]=l[x];
70 for(int j=1;j<=l[i];j++){
71 a[i][j]=a[x][j];
72 pos[i][j]=pos[x][j];
73 }
74 a[i][++l[i]]=y,pos[i][l[i]]=i;
75 ll s=S2[i][l[i]]=F[i][l[i]]=0;
76 L[l[i]]=1,R[l[i]]=l[i];
77 Q.clear(),Q.push_back(l[i]);
78 for(int j=l[i]-1;j;j--){
79 s+=d[a[i][j]][y];
80 S2[i][j]=get_S(i,j,l[i]-1)+s;
81 while ((!Q.empty())&&(j<L[Q.front()]))Q.pop_front();
82 F[i][j]=calc(i,j,Q.front());
83 while ((!Q.empty())&&(calc(i,R[Q.back()],j)<calc(i,R[Q.back()],Q.back())))Q.pop_back();
84 if (Q.empty())L[j]=1,R[j]=j;
85 else{
86 int p=Q.back(),l=L[p],r=R[p];
87 while (l<r){
88 int mid=(l+r>>1);
89 if (calc(i,mid,p)<calc(i,mid,j))r=mid;
90 else l=mid+1;
91 }
92 L[Q.back()]=l;
93 if (l==1)continue;
94 L[j]=1,R[j]=l-1;
95 }
96 Q.push_back(j);
97 }
98 printf("%lld\n",(F[i][1]<<1));
99 }
100 }
101 return 0;
102 }

[hdu7097]Just a Data Structure Problem的更多相关文章

  1. CDOJ 483 Data Structure Problem DFS

    Data Structure Problem Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/proble ...

  2. ZOJ 4009 And Another Data Structure Problem(ZOJ Monthly, March 2018 Problem F,发现循环节 + 线段树 + 永久标记)

    题目链接  ZOJ Monthly, March 2018 Problem F 题意很明确 这个模数很奇妙,在$[0, mod)$的所有数满足任意一个数立方$48$次对$mod$取模之后会回到本身. ...

  3. [hdu7099]Just Another Data Structure Problem

    不难发现,问题即求满足以下条件的$(i,j)$对数: 1.$1\le i<j\le n$且$a_{i}=a_{j}$ 2.$\min_{i\le k\le j}y_{k}\ge l$且$\max ...

  4. HDU 6649 Data Structure Problem(凸包+平衡树)

    首先可以证明,点积最值的点对都是都是在凸包上,套用题解的证明:假设里两个点都不在凸包上, 考虑把一个点换成凸包上的点(不动的那个点), 不管你是要点积最大还是最小, 你都可以把那个不动的点跟原点拉一条 ...

  5. [LeetCode] Add and Search Word - Data structure design 添加和查找单词-数据结构设计

    Design a data structure that supports the following two operations: void addWord(word) bool search(w ...

  6. hdu-5929 Basic Data Structure(双端队列+模拟)

    题目链接: Basic Data Structure Time Limit: 7000/3500 MS (Java/Others)    Memory Limit: 65536/65536 K (Ja ...

  7. HDU 5929 Basic Data Structure 模拟

    Basic Data Structure Time Limit: 7000/3500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Oth ...

  8. hdu 4217 Data Structure? 树状数组求第K小

    Data Structure? Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) ...

  9. (*medium)LeetCode 211.Add and Search Word - Data structure design

    Design a data structure that supports the following two operations: void addWord(word) bool search(w ...

随机推荐

  1. python paramiko实现ssh上传下载执行命令

    paramiko ssh上传下载执行命令 序言 最近项目经常需要动态在跳板机上登录服务器进行部署环境,且服务器比较多,每次完成所有服务器到环境部署执行耗费大量时间.为了解决这个问题,根据所学的执行实现 ...

  2. pymysql基础

    一,基本使用 倒入模块 import pymysql conn=pymysql.connect( host="数据库地址,本机是localhost,别的机器是ip", user=& ...

  3. FFT 的一些技巧

    三次变两次 FFT 我们发现: \[(F(x)+iG(x))^2=F(x)^2-G(x)^2+2iF(x)G(x) \] 也就是说,我们把 \(F(x)\) 作为实部,\(G(x)\) 作为虚部,那么 ...

  4. 题解 SP6779 【GSS7 - Can you answer these queries VII】

    题目传送门 题目大意 给出一个\(n\)个点的树,每个点有权值.有\(m\)次操作,每次要么查询一条链上的最大子段和,要么把一条链的权值都修改为一个常数. \(n,m\le 10^5\) 思路 如果是 ...

  5. cf1082D Maximum Diameter Graph(构造+模拟+细节)

    QWQ不得不说 \(cf\)的\(edu\ round\)出这种东西 有点太恶心了 题目大意:给你\(n\)个点,告诉你每个点的最大度数值(也就是说你的度数要小于等于这个),让你构造一个无向图,使其满 ...

  6. 【UE4 C++】Slate 初探: Editor UI 与 Game UI

    概述 名词区分 Slate Slate 是完全自定义.与平台无关的UI框架 应用 可用于编辑器UI,编辑器的大部分界面都是使用 Slate 构建的 可做为游戏UI 可作为独立应用开发 只能 C++ 开 ...

  7. 反调试——11——检测TF标志寄存器

    反调试--11--检测TF标志寄存器 在intel的x86寄存器中有一种叫标志寄存器: 标志寄存器中的TF(Trap Flag)位,CPU在执行完一条指令后,如果检测到标志寄存器的TF位为1,则会产生 ...

  8. Flink sql 之 join 与 StreamPhysicalJoinRule (源码解析)

    源码分析基于flink1.14 Join是flink中最常用的操作之一,但是如果滥用的话会有很多的性能问题,了解一下Flink源码的实现原理是非常有必要的 本文的join主要是指flink sql的R ...

  9. 【Golang详解】go语言中并发安全和锁

    go语言中并发安全和锁 首先可以先看看这篇文章,对锁有些了解 [锁]详解区分 互斥锁.⾃旋锁.读写锁.乐观锁.悲观锁 Mutex-互斥锁 Mutex 的实现主要借助了 CAS 指令 + 自旋 + 信号 ...

  10. 按照工业标准1英寸=25.4mm,而在电子元件成像领域Sensor尺寸1英寸=16mm。

    按照工业标准1英寸=25.4mm,而在电子元件成像领域Sensor尺寸1英寸=16mm. 我们平常所说的CCD/CMOS的尺寸,实际上是指Sensor对角线的长度,这一点跟我们平常所说的屏幕尺寸是一样 ...