您的位置:首页 > 其它

Ping pong UVA - 1428 树状数组

2017-11-21 18:06 411 查看
这个题目,就是对于一个树状数组的考察,更新,求和,先说一下题目的意思,题目的要求就是需要统一,满足要求的情况下,有多少中可能,我们需要做的就是枚举裁判,然后对于一个裁判,a0 在a1到ai-1比他小的有ci个,那就有i - ci个比他大的, 同样我们需要统计在ai+1 到an-1 有di个比ai小的,然后就会有 n - 1 - i - di 个比他大的,然后根据加法原理,得到的公式为(LL)(c[i]*(n - 1 - i - d[i])) + (LL)(d[i]*(i - c[i])); 然后O(n)的枚举就可以了。注意long
long

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <map>
#include <queue>
#include <math.h>
#include <stack>
#include <utility>
#include <string>
#include <sstream>
#include <cstdlib>
#include <set>
#define LL long long
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 100000 + 10;
int dir[4][2] = {{1,0},{0,1},{-1,0},{0,-1}};
int k[maxn];
int c[maxn];
int num[maxn];
int d[maxn];
int n;
int lowbit(int x)
{
return x & (-x);
}
void add(int x,int d)
{
while(x <= maxn)
{
k[x] += d;
x += lowbit(x);
}
}
int sum(int x)
{
int ans = 0;
while(x > 0)
{
ans += k[x];
x -= lowbit(x);
}
return ans;

}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
memset(num,0,sizeof(num));
memset(c,0,sizeof(c));
memset(d,0,sizeof(d));
memset(k,0,sizeof(k));
scanf("%d",&n);
for(int i = 0; i < n; i++)
{
scanf("%d",&num[i]);
}
for(int i = 0; i < n; i++)
{
add(num[i],1);
c[i] = sum(num[i] - 1);
}
memset(k,0,sizeof(k));
for(int i = n - 1; i >= 0; i--)
{
add(num[i],1);
d[i] = sum(num[i] - 1);
}
LL cnt = 0;
for(int i = 0; i < n; i++)
{
cnt += (LL)(c[i]*(n - 1 - i - d[i])) + (LL)(d[i]*(i - c[i]));
}
printf("%lld\n",cnt);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: