2431:House Moving

問題文
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2431











(全ての荷物の重さ)-(最長増加部分列の重さ)が答えになる。

dp[ i ]:= i 番目を最後尾とする最長増加部分列の重さ
dp[ i ]=max(dp[ j ] | 0 < j < i) + ( i 番目の荷物の重さ)


i未満の番号の最長増加部分列の最大値を求めるとこに
セグメント木を使った。[ 1, i )だけなのでBITでも解ける。

#include<iostream>
#include<vector>
#include<algorithm>
#include<climits>

const int MAX_N=1<<17;

typedef long long ll;

using namespace std;


ll n,dat[2*MAX_N-1];

void init(int n_){
	n=1;
	while(n<n_)n*=2;
}

void update(int k,ll a){
	k+=n-1;
	dat[k]=a;
	
	while(k>0){
		k=(k-1)/2;
		dat[k]=max(dat[2*k+1],dat[2*k+2]);
	}
}

ll query(int a,int b,int k,int l,int r){
	if(r<=a || b<=l)return 0;
	if(a<=l && r<=b)return dat[k];
	else {
		ll vl=query(a,b,k*2+1,l,(l+r)/2);
		ll vr=query(a,b,k*2+2,(l+r)/2,r);
		return max(vl,vr);
	}
}

int main(void){
	
	ll in,m,ans=0;
	
	cin >> m;
	
	init(m);
	
	for(int i=0;i<m;i++){
		cin >> in;
		update(in,in+query(1,in,0,0,n));
	}
	cout << m*(m+1)/2-query(1,m+1,0,0,n) << endl;
	
	return 0;
}