APIO 2014 시퀀스 분할 bzoj3675

1735 단어 dp
처음 출력 98, 처음 발을 동동 구르는 자세가 틀렸다...황 선배의 블로그를 슬쩍 쳐다보니 get이 새로운 자세, 분노 코드, 그리고 98...마지막에 괄호의 위치를 잘못 놓았다...너무 은폐해서 육안으로 debug가 나오지 못했다.QAQQQQQQQQQQQQQQQ...너무 약해...
이 문제는 분명히 Dp방정식 분정 f[i]=f[j]+s[j]*(s[i]-s[j])를 쓸 수 있다. 왜냐하면 이 문제는 실제적으로 자르는 순서와 무관하기 때문이다. 사실 이것은 답안의 모든 구간에 반드시 k를 곱한다는 것을 분명히 증명한다.차(대충 뇌를 보충해 보았지만 실제 계산이 없었다) 그리고 둥지들은 항상 기쁘게 경사율 최적화를 쓸 수 있었다
당시 경사율 DP 특집 경기 분노 AK의 RP 어디 갔어 QAQQQQQQQQQQQ
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100005
#define LL long long
using namespace std;
LL sum[N],f[N],q[N],a[N],g[N];
int n,k;

LL read()
{
	LL x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x;
}

double calc(int j,int k)
{
        return (double)(sum[k]*sum[k]-sum[j]*sum[j]-g[k]+g[j])/(double)(sum[k]-sum[j]);
}

void work(int x)
{
        int h=1,t=0;
        for (int i=x;i<=n;i++)
        {
                while (h<t&&calc(q[t-1],q[t])>calc(q[t],i-1)) t--;q[++t]=i-1;
                while (h<t&&calc(q[h],q[h+1])<sum[i]) h++;int p=q[h];
                f[i]=g[p]+(sum[i]-sum[p])*sum[p];
        }
        for (int i=x;i<=n;i++) swap(f[i],g[i]);
}

void dp()
{
        for (int i=1;i<=k;i++)
                work(i);
        printf("%lld
",g[n]); } int main() { n=read();k=read(); for (int i=1;i<=n;i++) a[i]=read(); int top=0; for(int i=1;i<=n;i++) if(a[i]!=0) a[++top]=a[i]; n=top; for(int i=1;i<=n;i++) sum[i]=sum[i-1]+a[i]; dp(); return 0; }

좋은 웹페이지 즐겨찾기