您的位置:首页 > 其它

CF - 61E - Enemy is weak(树状数组)

2013-08-11 17:33 337 查看
题意:有n个数a1, a2, ..., an,问i < j < k且ai > aj > ak的三角对有多少对(3 <= n <= 10^6, 1 <= ai <= 10^9)。

题目链接:http://codeforces.com/problemset/problem/61/E

——>>对于一个位置j,其左边有L[j]个比aj大的数,其右边有R[j]个比aj小的数,那么,ai可从L[j]个数中取,ak可从R[j]个数中取,此时可组成L[j] * R[j]个三角对,枚举j的位置,求和。

由于数据量不小,2层for以O(n^2)找L与R已超过题目所允许的时间,这里恰恰可用树状数组来求得R,而L可根据R推出。

因为1 <= ai <= 10^9,数组开不下,但输入个数不超过10^6,所以可做一个重映射,使输入的数根据大小重映射为1到n,设重映射后的数组为f。

用树状数组求出R后,因为R[i]表示第i个数的右边有多少个比f[i]小的数,而第i个数的右边共有n-i个数,所以第i个数的右边有n - i - R[i]个比f[i]大的数,而整个f有n-f[i]个比f[i]大的数,所以第i个数的左边有n - f[i] - (n - i - R[i]) = R[i] - f[i] + i个比f[i]大的数,即L[i] = R[i] - f[i] + i。

#include <cstdio>
#include <algorithm>
#include <cstring>

using namespace std;

const int maxn = 1000000 + 10;
int n, f[maxn], C[maxn], L[maxn], R[maxn];

struct node{
int id;
int val;
bool operator < (const node& e) const{
return val < e.val;
}
}a[maxn];

int lowerbit(int x){
return x & (-x);
}

void add(int x, int v){
while(x <= n){
C[x] += v;
x += lowerbit(x);
}
}

int sum(int x){
int ret = 0;
while(x){
ret += C[x];
x -= lowerbit(x);
}
return ret;
}

int main()
{
int i;
while(scanf("%d", &n) == 1){
for(i = 1; i <= n; i++){
scanf("%d", &a[i].val);
a[i].id = i;
}
sort(a+1, a+1+n);
for(i = 1; i <= n; i++) f[a[i].id] = i;     //重映射
memset(C, 0, sizeof(C));
for(i = n; i >= 1; i--){
R[i] = sum(f[i]);
add(f[i], 1);
}
for(i = 1; i <= n; i++) L[i] = R[i] - f[i] + i;
long long ret = 0;
for(i = 2; i < n; i++) ret += (long long)L[i] * R[i];
printf("%I64d\n", ret);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: