链接:hdu 2492
1 3 1 2 3
1
有N个人从左到右排成一排,每个人有一个唯一的技能值,选出三个人——两名比赛选手还有一名裁判,裁判的技能值不能比这两个人都高,也不能比这两个人都低,并且这两个人到裁判的距离总和不能大于他们之间的距离。不同的人比赛或者比赛时候的裁判不同算不同的比赛,求一共能比几场。
将题意抽象出来,就是已知数列{aN}(3<=N<=20000)其中ai,从左往右取三个不同的数(可以不相邻),求使这三个数排成升序或降序的取法数。
设L为第i个人左边的人中,技能值小于他的人数, R为第i个人左边的人中,技能值小于他的人数,那么选第i个人作为裁判的方法数Ans[i]等于(L[i] * (N - i - R[i]) +(i - 1 - L[i]) * R[i]),最终输出的答案就是枚举N个人,对Ans[i]求和。那么现在的问题就是如何求L和R数组,那么很清晰,直接树状数组对区间求和即可,方法类似于求逆序数。
/****************************>>>>HEADFILES<<<<****************************/ #include <set> #include <map> #include <list> #include <cmath> #include <queue> #include <vector> #include <cstdio> #include <string> #include <cstring> #include <iomanip> #include <iostream> #include <sstream> #include <algorithm> using namespace std; /****************************>>>>>DEFINE<<<<<*****************************/ #define fst first #define snd second #define root 1,N,1 #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define PB(a) push_back(a) #define MP(a,b) make_pair(a,b) #define CASE(T) for(scanf("%d",&T);T--;) #define FIN freopen("input.txt","r",stdin) #define FOUT freopen("output.txt","w",stdout) //#pragma comment(linker, "/STACK:1024000000,1024000000") //typedef __int64 LL; typedef long long LL; typedef pair<int, int> PII; const int INF = 0x3f3f3f3f; const int maxn = 100000 + 5; const int maxm = 20000 + 5; /****************************>>>>SEPARATOR<<<<****************************/ int T, N, MAX, a[maxm]; int S[maxn], L[maxm], R[maxm]; inline int lowbit(int x) { return x & (-x); } void Add(int pos, int val) { for(; pos <= MAX; pos += lowbit(pos)) S[pos] += val; } int Query(int pos) { int ret = 0; for(; pos > 0; pos -= lowbit(pos)) ret += S[pos]; return ret; } int main() { // FIN; CASE(T) { scanf("%d", &N); memset(S, 0, sizeof(S)); MAX = 0; for(int i = 1; i <= N; i++) { scanf("%d", &a[i]); MAX = max(MAX, a[i]); } for(int i = 1; i <= N; i++) { L[i] = Query(a[i]); Add(a[i], 1); } memset(S, 0, sizeof(S)); for(int i = N; i >= 1; i--) { R[i] = Query(a[i]); Add(a[i], 1); } LL ans = 0; for(int i = 2; i < N; i++) { ans += (L[i] * (N - i - R[i]) + (i - 1 - L[i]) * R[i]); } cout << ans << endl; } }
版权声明:本文为博主原创文章,未经博主允许不得转载。
POJ 3928 & hdu 2492 & Uva1428 PingPong 【树状数组】
原文地址:http://blog.csdn.net/acmore_xiong/article/details/47451455