E. Alice and the Unfair Game(推导线段树)
题:https://codeforces.com/contest/1236/problem/E
粗自:https://www.cnblogs.com/YSFAC/p/11715522.html
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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); }