Online JudgeProblem SetAuthorsOnline ContestsUser
Web Board
Home Page
F.A.Qs
Statistical Charts
Problems
Submit Problem
Online Status
Prob.ID:
Register
Update your info
Authors ranklist
Current Contest
Past Contests
Scheduled Contests
Award Contest
User ID:
Password:
  Register

dp+线段树可做

Posted by marszed at 2018-04-10 09:27:25 on Problem 3278
对于当前考虑到的第 i 个位置:
首先 f(i)=f(i-1)+1 如果i是偶数 则 f(i)=min( f(i) , f(i/2)+1 )
对于从右边过来的情况 很多人说不满足无后效性,但我想了下:
这种情况一定是 从 i 左边的某个点通过 *2 的方法 跳过来然后直接往左--
就是从 i 左边的某一点 j 先*2 再往左走 总计也就是 f(j) +1 +2*j -i
所以开个线段树保存 f(j)+2*j 



#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define mid (l+r)/2
#pragma warning(disable:4996)
using namespace std;

const int maxn = 2e5 + 10;
const int inf = 0x3f3f3f3f;

int n, k;

int dp[maxn], cover[maxn << 2];

void pushup(int rt)
{
	cover[rt] = min(cover[rt << 1], cover[rt << 1 | 1]);
}

void build(int rt, int l, int r)
{
	if (l == r)
	{
		if (l <= n) cover[rt] = dp[l]+2*l;
		return;
	}
	build(rt << 1, l, mid);
	build(rt << 1 | 1, mid + 1, r);
	pushup(rt);
}

int query(int rt, int l, int r, int qstart, int qend)
{
	if (qstart <= l&&r <= qend)
		return cover[rt];
	int ans = inf;
	if (qstart <= mid) ans = query(rt << 1, l, mid, qstart, qend);
	if (mid < qend) ans = min(ans, query(rt << 1 | 1, mid + 1, r, qstart, qend));
	return ans;
}

void update(int rt, int l, int r, int pos, int val)
{
	if (l == r)
	{
		cover[rt] = val;
		return;
	}
	if (pos <= mid) update(rt << 1, l, mid, pos, val);
	else update(rt << 1 | 1, mid + 1, r, pos, val);
	pushup(rt);
}

int main()
{

	ios::sync_with_stdio(false);

	memset(dp, 0x3f, sizeof(dp));
	memset(cover, 0x3f, sizeof(cover));
	cin >> n >> k;
	if (k <= n)
	{
		cout << n - k << endl;
		return 0;
	}
	for (int i = 0; i <= n; i++)
		dp[i] = n - i;
	build(1, 0, maxn);
	for (int i = n + 1; i <= k; i++)
	{
		dp[i] = min(dp[i], dp[i - 1] + 1);
		if (i % 2 == 0) dp[i] = min(dp[i], dp[i / 2] + 1);
		int pos = i / 2 - 1;
		while (pos * 2 <= i) pos++;
		dp[i] = min(dp[i], query(1, 0, maxn, pos, i - 1) + 1 - i);
		update(1, 0, maxn, i, dp[i] + 2 * i);
	}
	cout << dp[k] << endl;
	return 0;
}

Followed by:

Post your reply here:
User ID:
Password:
Title:

Content:

Home Page   Go Back  To top


All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator