Codeforces Round #446 (Div. 2) B 题
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.
【题意】
好理解 杀死前面的人, 问最后活下几个人, 最后一个人 一定活
【思路】
先把 i - li 算出来, 负值 赋值为1
从后面往前扫, 维护一个最小值, 前面的 i 如果比这个最小值 大 就一定死掉
【代码实现】
#include <bits/stdc++.h> #include <iostream> #include <stdio.h> #include <algorithm> #include <cmath> #include <math.h> #include <cstring> #include <string> #include <queue> #include <deque> #include <stack> #include <stdlib.h> #include <list> #include <map> #include <set> #include <bitset> #include <vector> #define mem(a,b) memset(a,b,sizeof(a)) #define findx(x) lower_bound(b+1,b+1+bn,x)-b #define FIN freopen("input.txt","r",stdin) #define FOUT freopen("output.txt","w",stdout) #define S1(n) scanf("%d",&n) #define SL1(n) scanf("%I64d",&n) #define S2(n,m) scanf("%d%d",&n,&m) #define SL2(n,m) scanf("%I64d%I64d",&n,&m) #define Pr(n) printf("%d\n",n) #define lson rt << 1, l, mid #define rson rt << 1|1, mid + 1, r using namespace std; typedef long long ll; const double PI=acos(-1); const int INF=0x3f3f3f3f; const double esp=1e-6; const int maxn=1e6+5; const int MAXN=50005; const int MAX=1<<22; const int MOD=1e9+7; const int mod=1e9+7; int dir[5][2]={0,1,0,-1,1,0,-1,0}; ll inv[maxn*2]; inline void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){ x=1; y=0; d=a; }else{ ex_gcd(b,a%b,d,y,x); y-=x*(a/b);};} inline ll gcd(ll a,ll b){ return b?gcd(b,a%b):a;} inline ll exgcd(ll a,ll b,ll &x,ll &y){if(!b){x=1;y=0;return a;}ll ans=exgcd(b,a%b,x,y);ll temp=x;x=y;y=temp-a/b*y;return ans;} inline ll lcm(ll a,ll b){ return b/gcd(a,b)*a;} inline ll qpow(ll x,ll n){ll res=1;for(;n;n>>=1){if(n&1)res=(res*x)%MOD;x=(x*x)%MOD;}return res;} inline ll inv_exgcd(ll a,ll n){ll d,x,y;ex_gcd(a,n,d,x,y);return d==1?(x+n)%n:-1;} inline ll inv1(ll b){return b==1?1:(MOD-MOD/b)*inv1(MOD%b)%MOD;} inline ll inv2(ll b){return qpow(b,MOD-2);} int b[maxn]; int vis[maxn]; struct math_tree{ int n; int a[MAX],Max[MAX],Min[MAX]; int tree[MAX]; void init(int N) { n=N; for(int i=0;i<=N;i++) Max[i]=-(Min[i]=INF); } void update(int k,int num)//单点更新 { a[k]=num; while(k<=n) { tree[k]+=num; Min[k]=Max[k]=a[k]; int lk=k&(-k); for(int i=1;i<lk;i<<=1) { Max[k]=max(Max[k],Max[k-i]); Min[k]=min(Min[k],Min[k-i]); } k+=k&(-k);// lowbit(k)= k&(-k); } } int Sum(int k) { int sum=0; while(k) { sum+=tree[k]; k-=k&-k; } return sum; } int Get_Sum(int x,int y) { return Sum(y)-Sum(x-1); } int Qmax(int x,int y)//[x,y]区间最大值 { int ans=-INF; while(y>=x) { ans=max(a[y], ans); y--; for(;y-(y&-y)>=x;y-=(y&-y)) ans=max(Max[y],ans); } return ans; } int Qmin(int x,int y)//[x,y] 区间最小值 { int ans=INF; while(y>=x) { ans=min(a[y],ans); y--; for(;y-(y&-y)>=x;y-=(y&-y)) ans=min(ans,Min[y]); } return ans; } }A; int main() { int n; while(~scanf("%d",&n)) { int x; A.init(n); for(int i=1;i<=n;i++) { S1(x); if(i-x<0) b[i]=1; else b[i]= i-x; A.update(i,b[i]); } int ans=1; for(int i=n-1;i>=1;i--) { // printf("%d\n",A.Qmin(i,n)); if(i<A.Qmin(i+1,n)) { ans++; // printf("**\n"); } } printf("%d\n",ans); } return 0; }