結果

問題 No.913 木の燃やし方
ユーザー leaf_1415leaf_1415
提出日時 2019-10-20 05:14:25
言語 C++11
(gcc 11.4.0)
結果
AC  
実行時間 433 ms / 3,000 ms
コード長 2,723 bytes
コンパイル時間 1,247 ms
コンパイル使用メモリ 73,500 KB
実行使用メモリ 23,204 KB
最終ジャッジ日時 2023-09-10 23:51:24
合計ジャッジ時間 16,837 ms
ジャッジサーバーID
(参考情報)
judge13 / judge15
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
5,392 KB
testcase_01 AC 2 ms
5,392 KB
testcase_02 AC 2 ms
5,480 KB
testcase_03 AC 4 ms
5,592 KB
testcase_04 AC 4 ms
5,604 KB
testcase_05 AC 4 ms
5,796 KB
testcase_06 AC 4 ms
5,544 KB
testcase_07 AC 3 ms
5,568 KB
testcase_08 AC 187 ms
22,952 KB
testcase_09 AC 181 ms
22,704 KB
testcase_10 AC 181 ms
22,684 KB
testcase_11 AC 184 ms
22,968 KB
testcase_12 AC 192 ms
23,016 KB
testcase_13 AC 185 ms
22,948 KB
testcase_14 AC 180 ms
23,156 KB
testcase_15 AC 179 ms
22,688 KB
testcase_16 AC 180 ms
23,024 KB
testcase_17 AC 178 ms
22,972 KB
testcase_18 AC 179 ms
23,072 KB
testcase_19 AC 187 ms
23,060 KB
testcase_20 AC 187 ms
23,016 KB
testcase_21 AC 255 ms
23,024 KB
testcase_22 AC 306 ms
23,036 KB
testcase_23 AC 393 ms
22,956 KB
testcase_24 AC 428 ms
23,020 KB
testcase_25 AC 433 ms
23,104 KB
testcase_26 AC 189 ms
23,032 KB
testcase_27 AC 193 ms
22,992 KB
testcase_28 AC 214 ms
22,972 KB
testcase_29 AC 227 ms
23,040 KB
testcase_30 AC 237 ms
22,968 KB
testcase_31 AC 198 ms
23,108 KB
testcase_32 AC 186 ms
23,100 KB
testcase_33 AC 188 ms
23,204 KB
testcase_34 AC 223 ms
22,964 KB
testcase_35 AC 229 ms
22,968 KB
testcase_36 AC 236 ms
23,032 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#define llint long long
#define inf 1e18

using namespace std;

typedef pair<llint, llint> P;

struct LiChaoTree{
	int size;
	vector<P> seg;
	vector<llint> x;
	
	LiChaoTree(){}
	LiChaoTree(int size){
		this->size = size;
		seg.resize(1<<(size+1));
		x.resize(1<<size);
	}
	
	void init()
	{
		for(int i = 0; i < (1<<(size+1)); i++) seg[i] = make_pair(0, inf);
		for(int i = 0; i < (1<<size); i++) x[i] = i;  //オーバーフローに注意
	}
	llint calc(P f, llint x)
	{
		return f.first * x + f.second;
	}
	llint query(int i) //x[i]における最小値を取得
	{
		llint X = x[i], ret = inf;
		i += (1 << size);
		while(i >= 1){
			ret = min(ret, calc(seg[i], X));
			i /= 2;
		}
		return ret;
	}
	void add(int k, int l, int r, P f)
	{
		int m = (l+r)/2;
		if(calc(f, x[m]) < calc(seg[k], x[m])) swap(seg[k], f);
		bool L = (calc(f, x[l]) < calc(seg[k], x[l])), R = (calc(f, x[r]) < calc(seg[k], x[r]));
		if(L == R) return;
		if(L) add(k*2, l, m, f);
		if(R) add(k*2+1, m+1, r, f);
	}
	void addSegment(int a, int b, int k, int l, int r, P f)
	{
		if(b < l || r < a) return;
		if(a <= l && r <= b){
			add(k, l, r, f);
			return;
		}
		addSegment(a, b, k*2, l, (l+r)/2, f);
		addSegment(a, b, k*2+1, (l+r)/2+1, r, f);
	}
	void addSegment(int a, int b, llint p, llint q) //区間[x[a], x[b]]に線分px+qを追加
	{
		addSegment(a, b, 1, 0, (1<<size)-1, make_pair(p, q));
	}
	void addLine(llint p, llint q) //直線px+qを追加
	{
		return addSegment(0, (1<<size)-1, p, q);
	}
};

llint n;
llint a[200005], s[200005];
LiChaoTree lct;
llint ans[200005];

void calc(llint l, llint r)
{
	if(l > r) return;
	if(l == r){
		ans[l] = min(ans[l], s[r]-s[l-1] + 1);
		return;
	}
	llint m = (l+r)/2;
	
	llint size = 0;
	for(int len = r-l+2; len; len/=2) size++;
	lct = LiChaoTree(size);
	
	lct.init();
	for(int i = 0; i < (1<<size); i++) lct.x[i] = l-1+i;
	
	for(llint i = l-1; i < m; i++) lct.addLine(-2*i, i*i-s[i]);
	llint mn = inf;
	for(llint i = r; i >= m+1; i--){
		mn = min(mn, lct.query(i-(l-1)) + i*i + s[i]);
		ans[i] = min(ans[i], mn);
	}
	
	lct.init();
	for(int i = 0; i < (1<<size); i++) lct.x[i] = l-1+i;
	
	for(llint i = m+1; i <= r; i++) lct.addLine(-2*i, i*i+s[i]);
	mn = inf;
	for(llint i = l-1; i < m; i++){
		mn = min(mn, lct.query(i-(l-1)) + (i*i - s[i]) );
		ans[i+1] = min(ans[i+1], mn);
	}
	
	calc(l, m);
	calc(m+1, r);
}

int main(void)
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	
	cin >> n;
	for(int i = 1; i <= n; i++) cin >> a[i];
	for(int i = 1; i <= n; i++) s[i] = s[i-1] + a[i];
	
	for(int i = 1; i <= n; i++) ans[i] = inf;
	calc(1, n);
	
	for(int i = 1; i <= n; i++) cout << ans[i] << "\n";
	flush(cout);
	
	return 0;
}
0