题解:P12675 「LAOI-8」Boundary
2672434062xzl · · 题解
考虑动态规划,设
赋值
注意到在第二组测试数据中两个赋值后的区间之间也可以赋值,若第一个区间右端点为
令
综上,可以得到
拆掉绝对值得
典型的二维偏序问题,可以用树状数组解决,时间复杂度
参考程序:
#include<iostream>
#include<cstring>
const int N=1e6+10,INF=0x3f3f3f3f;
using namespace std;
int n;
int a[N],tr1[N],tr2[N],dp[N],minn[N];
int query(int x,int tr[]){
int ans=INF;
for(;x;x-=x&-x)ans=min(tr[x],ans);
return ans;
}
void update(int x,int v,int tr[]){
for(;x<=n;x+=x&-x)tr[x]=min(tr[x],v);
}
int main() {
int t;
for(cin>>t;t;--t){
memset(tr1,INF,sizeof tr1);
memset(tr2,INF,sizeof tr2);
memset(minn,INF,sizeof minn);
memset(dp,INF,sizeof dp);
cin>>n;
for(int i=1;i<=n;++i)scanf("%d",&a[i]);
dp[0]=0;
update(a[1],-a[1]-1,tr1);
update(n-a[1]+1,a[1]-1,tr2);
for(int i=2;i<=n;++i){
dp[i]=i+1+min(a[i]+query(a[i],tr1),-a[i]+query(n-a[i]+1,tr2));
minn[i]=min(minn[i-1],dp[i-1]+2-i);
update(a[i],-a[i]+min(dp[i-1]-i,minn[i]),tr1);
update(n-a[i]+1,a[i]+min(dp[i-1]-i,minn[i]),tr2);
}
printf("%d\n",dp[n]);
}
return 0;
}