제출 #101355

#제출 시각아이디문제언어결과실행 시간메모리
101355DystoriaXSplit the sequence (APIO14_sequence)C++14
71 / 100
2044 ms86776 KiB
#include <bits/stdc++.h>

#define ld long double

using namespace std;

struct Line{
	long long m, c;
	int idx;

	long long getY(long long x){
		return m * x + c;
	}

	ld getX(Line o){
		return (ld) (o.c - c) / (ld) (m - o.m);
	}
};

Line ch[100010];
int sz = 0, opt = 0;
int n, k;
int a[100010];
long long pref[100010];
long long dp[100010];
int bt[100010][210];

bool cmp(Line a, Line b, Line c){
	return a.getX(b) > a.getX(c);
}

/*void add(Line l){
	if(sz > 0){
		if(ch[sz - 1].m == l.m && ch[sz - 1].c > l.c) return;
		if(ch[sz - 1].m == l.m) sz--;
	}

	while(sz >= 2 && !cmp(l, ch[sz - 1], ch[sz - 2])) sz--;
	ch[sz++] = l;
}*/

/*pair<long long, int> findOpt(long long x){
	if(opt >= sz) opt = sz - 1;
	
	while(opt + 1 < sz && ch[opt].getY(x) <= ch[opt + 1].getY(x)) opt++;

	return {ch[opt].getY(x), ch[opt].idx};
}*/

void btrack(int i, int j){
	if(i == 0 || j == 0) return;
	btrack(bt[i][j], j - 1);
	printf("%d ", i);
}

int main(){
	scanf("%d%d", &n, &k);

	for(int i = 1; i <= n; i++){
		scanf("%d", &a[i]);
		pref[i] = pref[i - 1] + a[i];
	}

	//Base Case, k = 1
	for(int i = 1; i < n; i++){
		dp[i] = pref[i] * (pref[n] - pref[i]);
		//cout << i << " " << 1 << " " << dp[i][1].first << endl;
	}

	// DP formula:
	// dp[i][j] = max(dp[t][j - 1] + cost(t + 1, i) * cost(i + 1, n))
	// for t < i, where cost(i, j) = pref[j] - pref[i - 1]
	// Hence, simplifying the formula gives:
	// dp[i][j] = max(dp[t][j - 1] - pref[t] * pref[n] + pref[t] * pref[i]) + pref[i] * (pref[n] - pref[i])
	// Line equation:
	// m = pref[t]
	// x = pref[i]
	// c = dp[t][j - 1] - pref[t] * pref[n]
	// Note that dp[i][j] is defined for j <= i
	Line l;

	for(int j = 2; j <= k; j++){
		sz = opt = 0;

		l = (Line({pref[j - 1], dp[j - 1] - pref[j - 1] * pref[n], j - 1}));
		//Add Line
		ch[sz++] = l;
		
		for(int i = j; i < n; i++){
			long long temp = dp[i], x = pref[i];

			//Query
			if(opt >= sz) opt = sz - 1;
			
			while(opt + 1 < sz && ch[opt].getY(x) <= ch[opt + 1].getY(x)) opt++;

			//Update DP
			dp[i] = ch[opt].getY(x); bt[i][j] = ch[opt].idx;
			dp[i] += pref[i] * (pref[n] - pref[i]);
			l = (Line({pref[i], temp - pref[i] * pref[n], i}));

			if(sz > 0){
				if(ch[sz - 1].m == l.m && ch[sz - 1].c > l.c) continue;
				if(ch[sz - 1].m == l.m) sz--;
			}

			while(sz >= 2 && !cmp(l, ch[sz - 1], ch[sz - 2])) sz--;
			ch[sz++] = l;
			//cout << i << " " << j << " " << dp[i][j].first << " bt: " << dp[i][j].second <<endl;
		}
	}

	long long mx = -1, id = -1;
	for(int i = k; i < n; i++){
		if(mx < dp[i]){
			mx = dp[i];
			id = i;
		}
	}

	printf("%lld\n", mx);
	btrack(id, k);

	printf("\n");

	return 0;
}

컴파일 시 표준 에러 (stderr) 메시지

sequence.cpp: In function 'int main()':
sequence.cpp:57:7: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  scanf("%d%d", &n, &k);
  ~~~~~^~~~~~~~~~~~~~~~
sequence.cpp:60:8: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
   scanf("%d", &a[i]);
   ~~~~~^~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...