hdu3507 경사율 최적화 dp

2547 단어
이 문제: n은 500000을 받을 수 있습니다. o(n^2)는 시간을 초과할 수 있습니다. 모든 것은 최적화할 수 있습니다.
이 문제의 동적 기획 방정식을 주의하십시오: dp[i]=max(dp[j]+(sum[i]-sum[j])^2+m;
간략화: dp[i]=max(dp[j]+sum[i]^2+sum[j]^2-2*sum[i]*sum[j]);단조로운 대기열로 직접 최적화할 수 없습니다. i와 j는 분리할 수 없습니다.
가령 j가 k보다 낫다고 가정하다
dp[j]+sum[i]^2+sum[j]^2-2*sum[i]*sum[j]즉,
dp[j]+sum[j]^2-(dp[k]+sum[k]^2)/(2*dp[j]-2*dp[k])즉, 두 점의 경사율이sum[i]보다 작다고 볼 수 있는데 여기서 g[j,k]로 j,k 두 점의 경사율을 나타낸다.
여기에는 두 가지 결론이 쓰인다.
1.g[j,k]2.g[i, j]설명:
g[i, j]g[i, j]>sum[i], g[j, k]>g[i, j]>sum[i];k우량
주의 사항:
1. 여기서sum[i]는 점차적으로 증가하고 g[j,k](사율)도 점차적으로 증가하기 때문에 매번 사율이sum[i]보다 큰 점을 만족시키지 못하면 이후에도 어떤sum[i]보다 크지 않기 때문에 팀을 나가야 한다.dp[i]를 계산할 때 팀의 우두머리에서 가장 좋은 것을 찾는다. 즉, g[q[head+1], q[head]<=sum[i]의 점을 만족시키지 못하는 것이다. 즉, 사율이 sum[i]보다 큰 점을 찾고 sum[i]보다 작거나 같은 점을 찾아낸다.같은 경우도 안 된다.
2. 매번 입대할 때마다 경사율의 단조로운 증가성을 확보해야 한다.i입대, g[i,j]>g[j,k];
다음은 코드입니다.
#include<iostream>
#include<vector>
#include<string>
#include<queue>
#include<map>
#include<cstdio>
#include<cstring>
#define maxn 500005
#define INF 0xfffffff
#define min(a,b) a<b?a:b
#define max(a,b) a>b?a:b
using namespace std;
int n,m,head,tail;
int sum[maxn],q[maxn],dp[maxn];
int getUp(int i,int j)
{
    return dp[i]+sum[i]*sum[i]-dp[j]-sum[j]*sum[j];
}
int getDown(int i,int j)
{
    return 2*sum[i]-2*sum[j];
}
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        sum[0]=dp[0]=0;//          0
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&sum[i]);
            sum[i]=sum[i-1]+sum[i];
        }
        head=tail=0;
        q[tail++]=0;// 0  ,         2  
        for(int i=1;i<=n;i++)
        {
            while(head+1<tail&&getUp(q[head+1],q[head])<=sum[i]*getDown(q[head+1],q[head]))//        g[j,k]<=sum[i]
            head++;
            dp[i]=dp[q[head]]+m+(sum[i]-sum[q[head]])*(sum[i]-sum[q[head]]);

            while(head+1<tail&&getUp(i,q[tail-1])*getDown(q[tail-1],q[tail-2])<=getUp(q[tail-1],q[tail-2])*getDown(i,q[tail-1]))//         g[i,j]<=g[j,k]         
            tail--;
            q[tail++]=i;
        }
        printf("%d
",dp[n]); } return 0; }

좋은 웹페이지 즐겨찾기