hdu 4000 Fruit Ninja
/* 题目: 给出序列,其中一个子序列为(x,y,z),问最多有多少个这样的子序列, 使得x<z<y,其中该序列为1到n的排列 分析: 由于是排列,所以不存在相同的元素,所以x,y,z互不相等。所以序列中 的大小关系可表示为 小中大+小大中 = 小__ __ ,所以答案 小大中 = 小__ __ -小中大 统计 小__ __可以统计该位后面的所有元素中比他大的个数为x,则 小__ __ = x*(x-1)/2 而统计小中大时,只需要统计前面比他小的以及后面比他大的个数x,y,则 小中大 = x*y 统计个数可以用树状数组来统计,树状数组可以统计出前面已加入的元素比 当前的元素小的个数 */ #include <iostream> #include <cstdio> #include <cstring> using namespace std; #define MOD 100000007 #define X 100005 int a[X]; long long c[X],big[X],sma[X]; int lowbit(int x) { return x & -x; } void modify(int x) { while(x<X) { c[x] = (c[x]+1)%MOD; x += lowbit(x); } } long long query(int x) { long long ret = 0; while(x>0) { ret += c[x]; ret %= MOD; x -= lowbit(x); } return ret; } int main() { freopen("sum.in","r",stdin); freopen("sum.out","w",stdout); int cnt = 0,t,n; cin>>t; while(t--) { printf("Case #%d: ",++cnt); scanf("%d",&n); memset(c,0,sizeof(c)); memset(big,0,sizeof(big)); memset(sma,0,sizeof(sma)); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); sma[i] = query(a[i]); ///统计前面比他小的个数 modify(a[i]); } memset(c,0,sizeof(c)); for(int i=n;i>=1;i--) ///统计后面比他大的个数 { big[i] = n-i-query(a[i]); modify(a[i]); } long long s = 0,b = 0; for(int i=1;i<=n;i++) { s = (s+(big[i]-1)*big[i]/2)%MOD; ///统计小__ __的个数 b = (b+big[i]*sma[i])%MOD; ///统计小中大的个数 } cout<<(s-b+MOD)%MOD<<endl; } return 0; }