考试总结

T2
\(f[i]\) 表示前 \(i\) 个数字全部删去所需要的最小步数;
那么就有转移方程 \(f[i]=min(f[j-1]+|a[i]-a[j]|)\)
时间复杂度是 \(n^2\) ,考虑拆开
\(a[i]>=a[j]\) \(f[i]=min(f[j+1])-a[j]+a[i]\)
否则 \(f[i]=min(f[j+1]+a[j]-a[i])\)
j属于1~i;
可以用权值线段树分别维护 \(f[j-1]-a[j]\)\(f[j-1]+a[j]\) 的最小值;
注意数值范围是1e9,需要离散化;

#include<iostream>
#include<cstdio>
#include<algorithm>
#define int long long
#define mid ((l+r)>>1)
#define l(o) (o<<1)
#define r(o) (o<<1|1)
using namespace std;
const int N=1e6+7;
const int inf=1e15;
const int INF=1e6;
struct node{
	int lc,rc,min1,min2;
}tr[N<<2];
int n,cnt,cur;
int a[N],f[N],wz[N],b[N];
void up(int o){
	tr[o].min1=min(tr[l(o)].min1,tr[r(o)].min1);
	tr[o].min2=min(tr[l(o)].min2,tr[r(o)].min2);
}

void build(int o,int l,int r){
//	if(a[2]!=cur) cout<<a[2]<<" "<<cur<<" ssss"<<"\n";
	tr[o].min1=tr[o].min2=inf;
	if(l==r){return;}
	build(l(o),l,mid);
	build(r(o),mid+1,r);
}


void change(int o,int l,int r,int k,int val1,int val2){
	if(l==r){
		tr[o].min1=min(tr[o].min1,val1);
		tr[o].min2=min(tr[o].min2,val2);
		return;
	}
	if(k<=mid) change(l(o),l,mid,k,val1,val2);
	if(k>mid) change(r(o),mid+1,r,k,val1,val2);
	up(o);
}

int ask(int o,int l,int r,int L,int R,int k){
//	cout<<l<<" "<<r<<" "<<L<<" "<<R<<endl;
	if(L<=l&&R>=r){
		if(k==1) return tr[o].min1;
		else return tr[o].min2;
	}
	int res=inf;
	if(L<=mid) res=min(res,ask(l(o),l,mid,L,R,k));
	if(R>mid) res=min(res,ask(r(o),mid+1,r,L,R,k));
	return res; 
}


main(){
	freopen("remove.in","r",stdin);
	freopen("remove.out","w",stdout);
	scanf("%lld",&n);
	for(int i=1;i<=n;i++){
		scanf("%lld",&a[i]);
		b[i]=a[i];
	}
	sort(b+1,b+n+1);
	unique(b+1,b+n+1)-b-1;
	for(int i=1;i<=n;i++){
		wz[i]=lower_bound(b+1,b+n+1,a[i])-b;
//		cout<<wz[i]<<"\n";
	}
//	cur=a[2];
	build(1,1,INF);
//	cout<<a[2]<<"\n";
	f[1]=inf;
	
	change(1,1,INF,wz[1],f[0]-a[1],f[0]+a[1]);
	for(int i=2;i<=n;i++){
//		cout<<"-->"<<ask(1,1,INF,1,wz[i],1)<<" "<<ask(1,1,INF,wz[i]+1,INF,2)<<"\n";
//		cout<<a[i]<<"\n";
		f[i]=min(ask(1,1,INF,1,wz[i],1)+a[i],ask(1,1,INF,wz[i]+1,INF,2)-a[i]);
		change(1,1,INF,wz[i],f[i-1]-a[i],f[i-1]+a[i]);
//		cout<<f[i]<<"\n";
	}
	cout<<f[n];
	return 0;
}
/*
5
1 2 3 4 5
*/
posted @ 2020-09-14 07:24  Aswert  阅读(114)  评论(0编辑  收藏  举报