E. Alice and the Unfair Game(推导线段树)

题:https://codeforces.com/contest/1236/problem/E

粗自:https://www.cnblogs.com/YSFAC/p/11715522.html

#include<bits/stdc++.h>
using namespace std;
#define lson root<<1,l,midd
#define rson root<<1|1,midd+1,r
typedef long long ll;
const int M=1e5+5;
ll a[M],tree[M<<2],lz[M<<2];
ll L[M],R[M];
void build(ll root,ll l,ll r){
    if(l==r){
        tree[root]=l;
        return ;
    }
    int midd=(l+r)>>1;
    build(lson);
    build(rson);
}
ll query(ll pos,ll root,ll l,ll r){
    if(l==r)
        return tree[root]+lz[root];
    ll midd=(l+r)>>1;
    if(pos<=midd)
        return query(pos,lson)+lz[root];
    else
        return query(pos,rson)+lz[root];
}
void add(int L,int R,int c,int root,int l,int r){
    if(L<=l&&r<=R){
        lz[root]+=c;
        return ;
    }
    int midd=(l+r)>>1;
    if(L<=midd)
        add(L,R,c,lson);
    if(R>midd)
        add(L,R,c,rson);
}
int main(){
    ll n,m;
    scanf("%I64d%I64d",&n,&m);
    for(int i=1;i<=m;i++)
        scanf("%I64d",&a[i]);
    if(n==1)
        return cout<<"0",0;
    //计算向右最多能走的距离 
    build(1,1,n);
    for(int i=1;i<=m;i++){
        ll l=1,r=n;
        ll qul=0,qur=0;
        while(l<=r){
            ll midd=(l+r)>>1;
            if(query(midd,1,1,n)<a[i]-i)
                qul=midd,l=midd+1;
            else
                r=midd-1;
        }
        qul++,l=1,r=n;
        while(l<=r){
            ll midd=(l+r)>>1;
            if(query(midd,1,1,n)<=a[i]-i)
                qur=midd,l=midd+1;
            else
                r=midd-1;
        }
        if(qul<=qur)
            add(qul,qur,-1,1,1,n);
    }
    for(int i=1;i<=n;i++)
        R[i]=min(query(i,1,1,n)+m+1,n);
    memset(tree,0,sizeof(tree));
    memset(lz,0,sizeof(lz));
    //计算向左最多能走的距离 
    build(1,1,n);
    for(int i=1;i<=m;i++){
        ll l=1,r=n;
        ll qul=0,qur=0;
        while(l<=r){
            ll midd=(l+r)>>1;
            if(query(midd,1,1,n)<a[i]+i)
                qul=midd,l=midd+1;
            else
                r=midd-1;
        }
        qul++,l=1,r=n;
        while(l<=r){
            ll midd=(l+r)>>1;
            if(query(midd,1,1,n)<=a[i]+i)
                qur=midd,l=midd+1;
            else
                r=midd-1;
        }
        if(qul<=qur)
            add(qul,qur,1,1,1,n);
    }
    for(int i=1;i<=n;i++)
        L[i]=max(query(i,1,1,n)-m-1,1ll);
    ll ans=0;
    for(int i=1;i<=n;i++)
        ans+=R[i]-L[i]+1;
    printf("%I64d",ans);
}
View Code

猜你喜欢

转载自www.cnblogs.com/starve/p/11736997.html