貌似以前做到过这题。。。结果没搞出来T T
现在终于会了!谁想出来的,这么巧妙>.<
首先二分总的勋章数,然后判断可行性。
判断方法(dp):
令a[i]表示i与1最少有多少相同勋章,b[i]表示i与1最多有多少相同勋章。
转移方程请自行脑补 or 见程序
最后判断a[n] == 0即可
1 /************************************************************** 2 Problem: 1863 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:44 ms 7 Memory:1976 kb 8 ****************************************************************/ 9 10 #include11 #include 12 13 using namespace std;14 const int N = 100005;15 int n, ans;16 int v[N], a[N], b[N];17 18 inline int read(){19 int x = 0;20 char ch = getchar();21 while (ch < '0' || ch > '9')22 ch = getchar();23 while (ch >= '0' && ch <= '9'){24 x = x * 10 + ch - '0';25 ch = getchar();26 }27 return x;28 }29 30 bool check(const int x){31 int i;32 a[1] = b[1] = v[1];33 for (i = 2; i <= n; ++i){34 a[i] = max(0, v[1] + v[i] + v[i - 1] - b[i - 1] - x);35 b[i] = min(v[i], v[1] - a[i - 1]);36 }37 return !a[n];38 }39 40 int main(){41 int i, l, r, mid;42 n = read();43 for (i = 1; i <= n; ++i)44 ans = max((v[i] = read()) + v[i - 1], ans);45 l = ans - 1, r = ans * 2;46 while (l + 1 < r){47 mid = l + r >> 1;48 if (check(mid)) r = mid;49 else l = mid;50 }51 printf("%d\n", r);52 return 0;53 }