Codeforces Round #446 (Div. 2) B. Wrath【模拟/贪心】
Hands that shed innocent blood!
There are n guilty people in a line, the i-th of them holds a claw with length Li. The bell rings and every person kills some of people in front of him. All people kill others at the same time. Namely, the i-th person kills the j-th person if and only if j < i and j ≥ i - Li.
You are given lengths of the claws. You need to find the total number of alive people after the bell rings.
The first line contains one integer n (1 ≤ n ≤ 106) — the number of guilty people.
Second line contains n space-separated integers L1, L2, ..., Ln (0 ≤ Li ≤ 109), where Li is the length of the i-th person's claw.
Print one integer — the total number of alive people after the bell rings.
4
0 1 0 10
1
2
0 0
2
10
1 1 3 0 0 0 2 1 0 3
3
In first sample the last person kills everyone in front of him.
【题意】: n个人排队,第i个人会杀死第j个人当且仅当j < i并且j ≥i-li,问最后有多少个人能幸存下来。
【分析】:从后往前扫,这样就避免了j<i的干扰,记录一下i-Li的最小值,就能判断第j个人是否会被杀死。
//
The i'th person will be alive if min(j - Lj) > i over all j > i.
Consider you know the jth person is alive or not if j > i and you have x = min(j - Lj) over all j > i. If x > i then the ith person will be alive.
And you can update x easily.
【代码】:
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int inf = 0x7fffffff; const int N = 1e6+10; int a[N],b[N],maxn; int main() { int n,ans; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); int maxn = n-a[n]; ans = 1; for(int i=n-1;i>=1;i--)//倒序,求活,即死的反面min(j - Lj) > i over all j > i. { if(i<maxn)//你的刀还无法触及我 { ans++;//存活√ } maxn = min(maxn,i-a[i]);//想要活?维护一个最小刀长,诶嘿嘿砍不到我~ } printf("%d\n",ans); return 0; }