zoukankan      html  css  js  c++  java
  • bzoj1863 [Zjoi2006]trouble 皇帝的烦恼

    Description

    经过多年的杀戮,秦皇终于统一了中国。为了抵御外来的侵略,他准备在国土边境安置 (n) 名将军。不幸的是这 (n) 名将军羽翼渐丰,开始展露他们的狼子野心了。他们拒绝述职、拒绝接受皇帝的圣旨。秦皇已经准备好了秘密处决这些无礼的边防大将。不过为防兵变,他决定先授予这些将军一些勋章,为自己赢得战略时间。将军们听说他们即将被授予勋章都很开心,他们纷纷上书表示感谢。第 (i) 个将军要求得到 (a_i) 枚不同颜色的勋章。但是这些将军都很傲气,如果两个相邻的将军拥有颜色相同的勋章他们就会认为皇帝不尊重他们,会立即造反(编号为i的将军和编号为 $ i+1$的将军相邻;因为他们驻扎的边境可以类似看成一个圆形,所以编号 (1) 和编号 (n) 的将军也相邻)。皇帝不得不满足每个将军的要求,但对他们的飞扬跋扈感到很气愤。于是皇帝决定铸造尽量少种类的勋章来满足这些狂妄者的要求。请问他至少要铸造多少种颜色的勋章?

    Input

    第一行有一个整数 (n(1leq nleq 20000))。接下来 (n) 行每行一个整数 (a_i),表示第 (i) 个将军要求得到多少种勋章。((1leq a_i leq100000)) 输出一个整数,即最少需要多少种勋章。

    Output

    4 2 2 1 1

    Sample Input

    4

    Solution

    这应该是我做过的最巧妙的题之一了。显然应该考虑二分答案,但问题是怎么(O(n)) (check)。正解是用一个巧妙的 (dp)(check)(mn[i])表示编号为 (i) 的人最少和编号为 (1) 的人有多少个重复的(mx[i]) 表示编号为 (i) 的人最多和编号为 (1) 的人有多少个重复的。假如现在二分到 (x) ,那么:

    (mx[i] = min(a[i], a[i] - mn[i - 1]))
    (mn[i] = max(0, a[i] - (x - a[i - 1] - a[1] + mx[i - 1])))

    这样最后检查一下 (mn[n]) 是否为 (0) 就可以了。

    #include<bits/stdc++.h>
    using namespace std;
    
    #define N 300001
    #define rep(i, a, b) for (int i = a; i <= b; i++)
    #define drp(i, a, b) for (int i = a; i >= b; i--)
    #define fech(i, x) for (int i = 0; i < x.size(); i++)
    #define ll long long
    
    inline int read() {
    	int x = 0; char ch = getchar(); while (!isdigit(ch)) ch = getchar();
    	while (isdigit(ch)) x = x * 10 + ch - '0', ch = getchar(); return x;
    }
    
    int n;
    ll a[N], mx[N], mn[N];
    
    bool check(int x) {
    	mx[1] = mn[1] = a[1];
    	rep(i, 2, n) mx[i] = min(a[i], a[1] - mn[i - 1]), mn[i] = max(0ll, a[i] - (x - a[i - 1] - a[1] + mx[i - 1]));
    	return !mn[n];
    }
    
    int main() {
    	n = read(); ll l = 0, r, ans; rep(i, 1, n) a[i] = read(), l = max(l, a[i] + a[i - 1]); r = l << 1;
    	while (l <= r) {
    		int mid = l + r >> 1;
    		if (check(mid)) ans = mid, r = mid - 1;
    		else l = mid + 1;
    	}
    	cout << ans; return 0;
    }
    
  • 相关阅读:
    HDU 5486 Difference of Clustering 图论
    HDU 5481 Desiderium 动态规划
    hdu 5480 Conturbatio 线段树 单点更新,区间查询最小值
    HDU 5478 Can you find it 随机化 数学
    HDU 5477 A Sweet Journey 水题
    HDU 5476 Explore Track of Point 数学平几
    HDU 5475 An easy problem 线段树
    ZOJ 3829 Known Notation 贪心
    ZOJ 3827 Information Entropy 水题
    zoj 3823 Excavator Contest 构造
  • 原文地址:https://www.cnblogs.com/aziint/p/8416285.html
Copyright © 2011-2022 走看看