挺巧的一道题,笨的办法就是暴力搜索,但是用树状数组可以很巧妙的解决。
这题实质上就是每次 update 更新 val+1,然后求每段区间的长度。
#include <stdio.h>
#include <iostream>
#include <string.h>
using namespace std;
#define LEN 100002
int tree[LEN+2];
int in[LEN+2];
int lmin[LEN+2], lmax[LEN+2], rmin[LEN+2], rmax[LEN+2];
int lowbit(int x) {
return x & (-x);
}
void update(int x) {
while(x <= LEN) {
tree[x]++;
x += lowbit(x);
}
}
int query(int x) {
int sum = 0;
while(x > 0) {
sum += tree[x];
x -= lowbit(x);
}
return sum;
}
int main() {
int files;
scanf("%d", &files);
while(files--) {
int n, i, j;
scanf("%d", &n);
for(i = 1; i <= n; i++) {
scanf("%d", &in[i]);
}
memset(tree, 0, sizeof(tree));
for(i = 1; i <= n; i++) {
update(in[i]);
lmin[i] = query(in[i]-1);
lmax[i] = i - lmin[i] - 1;
}
memset(tree, 0, sizeof(tree));
for(i = n, j = 1; i >= 1; i--, j++) {
update(in[i]);
rmin[i] = query(in[i]-1);
rmax[i] = j - rmin[i] - 1;
}
long long ans = 0;
for(i = 1; i <= n; i++) {
ans += lmin[i] * rmax[i] + lmax[i] * rmin[i];
}
cout<< ans<< endl;
}
return 0;
}

6万+

被折叠的 条评论
为什么被折叠?



