首先看到数据范围 10^6 肯定是 O(n) 或者一只老哥。
考虑把所有数减去 P,那么原问题就变成有多少和不小于 0 的子序列。
容易想到前缀和,那么相当于求不逆序对数量。
于是用树状数组求解即可。
注意判断从 11 开始的子串,相当于从 sum_i-sum_0其中 sum 表示前缀和。
特判或者加入一个 0皆可。
Code :
#include#define int long long using namespace std; inline int read(void) { register int x=0,sgn=1,ch=getchar(); while(ch<48||57 9) write(x/10); putchar(x%10+'0'); } #define lowbit(x) (x&(-x)) int n,P,Ans; int c[1000006],rnk[1000006],pre[1000006]; inline void add(int x) { while(x<=n) { ++c[x]; x+=lowbit(x); } } inline int qry(int x) { int v=0; while(x>0) { v+=c[x]; x-=lowbit(x); } return v; } signed main() { n=read(); for(register int i=1; i<=n; ++i) pre[i]=read(); P=read(); for(register int i=1; i<=n; ++i) pre[i]-=P; for(register int i=1; i<=n; ++i) rnk[i]=(pre[i]+=pre[i-1]); sort(rnk,rnk+n+1); unique(rnk,rnk+n+1); for(register int i=0; i<=n; ++i) pre[i]=lower_bound(rnk,rnk+n+1,pre[i])-rnk+1; ++n; for(register int i=0; i< n; ++i) { Ans+=qry(pre[i]); add(pre[i]); } write(Ans); puts(""); return 0; }


![P7868 [COCI2015-2016#2] VUDU 题解 P7868 [COCI2015-2016#2] VUDU 题解](http://www.mshxw.com/aiimages/31/312354.png)
