您的位置:首页 > 产品设计 > UI/UE

HDU 5147 Sequence II 【树状数组维护信息 + 后缀和思想】

2018-01-20 00:56 471 查看
传送门

// 给定一个四元组的定义, 问在n个数中有多少个这样的四元组. 具体定义请看题目~

// 那么也很明显的就是我们需要枚举中间一个值然后找旁边的两个满足的东西. 这里我枚举的是b, 那么对于一个下标i, 我们看它前面有多个比它小的, 以及后面有多少个二元组满足i < j && a[i] < a[j] , 前面那个信息很好维护就是扫一遍然后用树状数组维护下就行啦. 那么如何维护一个数后面有多少个可行性二元组了 ?

我们把信息进行拆解, 也就是二元组中也要满足一个顺序关系, 那么也可以用树状数组维护, 那么我们如何要一个下标后面的所有二元组了, 此时我们就需要用到后缀和的思想了, 也就是我们从后往前枚举对于每一个满足的二元组进行后缀求和那么就是一个下标的右边所有满足的条件的二元组个数了~~~ 具体细节请看代码.

AC Code

const int maxn = 5e4+5;
int cas=1;
int c[maxn], a[maxn];
int n;
void add(int x) { for(;x<=n;x+=x&-x) c[x]++; }
int getsum(int x) { int res=0; for(;x;x-=x&-x) res += c[x]; return res; }
int l[maxn], r[maxn];
void solve()
{
scanf("%d", &n); Fill(c, 0);
for (int i = 1 ; i <= n ; i ++) {
scanf("%d", &a[i]);
l[i] = getsum(a[i]);
add(a[i]);
}
Fill(c, 0); Fill(r, 0);
for (int i = n ; i >= 1 ; i --) {
r[i] = getsum(n) - getsum(a[i]) + r[i+1];
add(a[i]);
}
ll ans = 0;
for (int i = 2 ; i <= n - 2 ; i ++) {
ans += 1ll*l[i]*r[i+1];
}
printf("%lld\n", ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: