Codeforces Round #261 (Div. 2) D 树状数组应用

时间:2022-04-18 19:02:05

看着题意:[1,i]中等于a[i]的个数要大于[,jn]中等于a[j]的个数 且i<j,求有多少对这种(i,j)  ,i<j可是 i前面的合法个数 要大于j后面的 看起来非常像逆序数的样子,所以非常easy往树状数组想去,可是处理就看个人了,像我比赛的时候就处理得非常的麻烦,虽做出了可是花时间也多,经过杰哥的教育,事实上正着塞进树状数组 反着来找就能够了,灰常的简单清晰明了,贴一发纪念我的搓比...

int n;

int aa[1000000 + 55];
int bb[1000000 + 55]; int c[1000000 + 55]; map<int ,int > mp; ll lowbit(ll x) {
return x&(-x);
} void add(int i,int val) {
while(i <= n) {
c[i] += val;
i += lowbit(i);
}
} ll get_sum(int i) {
ll sum = 0;
while(i) {
sum += c[i];
i -= lowbit(i);
}
return sum;
} void init() {
memset(c,0,sizeof(c));
memset(aa,0,sizeof(aa));
memset(bb,0,sizeof(bb));
mp.clear();
} int main() {
while(scanf("%d",&n) == 1) {
init();
for(int i=1;i<=n;i++)scanf("%d",&aa[i]);
for(int i=1;i<=n;i++) {
mp[aa[i]]++;
bb[i] = mp[aa[i]];
add(bb[i],1);
}
mp.clear();
ll ans = 0ll;
for(int i=n;i>=1;i--) {
add(bb[i],-1);
mp[aa[i]]++;
int tmp = mp[aa[i]];
ans += i - get_sum(tmp) - 1;
}
cout<<ans<<endl;
}
return 0;
}