3156: 방어 준비

1197 단어
경사율 최적화가 생겨서DP문제를 풀었더니 손도 춥지 않고 다리도 아프지 않고 허리도 아프지 않아요. 분만에 해결해요.
공식은 아무렇게나 밀어주면 돼요. DP를 거꾸로 하면 유일하게 아버지를 괴롭히는 것은 f가 2차원을 열어야 해요. 현재 점을 찍거나 놓지 않으면 탑을 앞에서 놓을 수 있다는 뜻이에요. (뒤에?)탑을 놓은 상태가 옮겨오다.
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=1000010;
const int inf=1e9;
inline int read(){
	int x=0;char ch;
	while(ch<'0'||ch>'9')ch=getchar();
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x;
}
typedef long long ll;
ll f[N][2];													//0    1  
int q[N],head,tail,n,A[N];
double slop(int j,int k){
	return (double)(f[j][1]-f[k][1])/(j-k)+(double)(k+j+1)/2;
}
int main(){
	n=read();
	for(int i=1;i<=n;i++)A[i]=read();
	head=1;tail=1;
	q[head]=n;f[n][1]=A[n];f[n][0]=inf;
	for(int i=n-1;i>=1;i--){
		while(head<tail&&slop(q[head+1],q[head])>i)head++;
		int t=q[head];
		f[i][0]=f[t][1]+(ll)(t-i)*(t-i+1)/2;
		f[i][1]=min(f[i+1][1],f[i+1][0])+A[i];
		while(head<tail&&slop(q[tail-1],q[tail])<slop(q[tail],i))tail--;
		q[++tail]=i;
	}
	printf("%lld",min(f[1][0],f[1][1]));
	return 0;
}

좋은 웹페이지 즐겨찾기