标签:
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2048 Accepted Submission(s): 805
题意:给出1~N的一种排列,问存在多少个三元组(x,y,z) x < z < y 其中x y z 的位置递增
可先求出满足 x < y < z 和x < z < y的总数tot, 总数为:对于每一个数 x, 从x后面的位置中比x大的num个数中选择任意两个, 即 tot += comb[ num ][2]
再从总数tot中减去 x < y < z的数量即为答案, x < y < z 的个数为: 对于一个数y, 在y的前面比 y小的个数为 low, 在y的后面比y大的个数为 high, 根据组合原理,在low中选一个x, 在high中选一个z,共有low × high中情况
如何求 每个数的low值和high值, 就用树状数组来统计
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <string> #include <queue> #include <map> #define Lowbit(x) ((x) & (-x)) using namespace std; typedef long long LL; const int N = 100005; const int M = 100000007; int c[N], a[N]; LL low[N], high[N], comb[N][5]; int n; void pre_c() { for(int i = 0; i < N; ++i) for(int j = 0; j <= min(i,2); ++j) comb[i][j] = (i == 0 || j == 0) ? 1:((comb[i - 1][j] % M + comb[i - 1][j - 1]) % M); } void update(int pos) { while(pos <= n) { c[pos]++; pos += Lowbit(pos); } } LL sum(int pos) { LL res = 0; while(pos) { res += c[pos]; pos -= Lowbit(pos); } return res; } int main() { int _, v, cas = 1; pre_c(); scanf("%d", &_); while(_ --) { scanf("%d", &n); memset(c, 0, sizeof c); for(int i = 1; i <= n; ++i) { scanf("%d", &v); a[i] = v; low[i] = sum(v); update(v); high[i] = (n - v) - (i - 1 - low[i]); } // for(int i = 1; i <= n; ++i) printf("%lld %lld\n", low[i], high[i]); LL tot = 0; for(int i = 1; i <= n; ++i) { tot = tot % M + comb[ high[i] ][2]; tot = (tot - (low[i] % M * high[i] % M) + M) % M; } printf("Case #%d: %lld\n",cas++, tot % M ); } }
标签:
原文地址:http://www.cnblogs.com/orchidzjl/p/4731562.html