codeforces 61E 树状数组 逆向

来源:互联网 发布:js汉字转unicode编码 编辑:程序博客网 时间:2024/06/05 02:49

The Romans have attacked again. This time they are much more than the Persians but Shapur is ready to defeat them. He says: “A lion is never afraid of a hundred sheep”.

Nevertheless Shapur has to find weaknesses in the Roman army to defeat them. So he gives the army a weakness number.

In Shapur’s opinion the weakness of an army is equal to the number of triplets i, j, k such that i < j < k and ai > aj > ak where ax is the power of man standing at position x. The Roman army has one special trait — powers of all the people in it are distinct.

Help Shapur find out how weak the Romans are.

Input
The first line of input contains a single number n (3 ≤ n ≤ 106) — the number of men in Roman army. Next line contains n different positive integers ai (1 ≤ i ≤ n, 1 ≤ ai ≤ 109) — powers of men in the Roman army.

Output
A single integer number, the weakness of the Roman army.

Please, do not use %lld specificator to read or write 64-bit integers in C++. It is preffered to use cout (also you may use %I64d).

Example
Input
3
3 2 1
Output
1
Input
3
2 3 1
Output
0
Input
4
10 8 3 1
Output
4
Input
4
1 5 4 3
Output
1

题意是求 i小于j同时j小于 k && a[i]>a[j]>a[k] 的对数

二元的话就是树状数组求逆序对了

看了大神的博客好久
http://blog.csdn.net/acmmmm/article/details/38427881
原来树状数组还能这么弄 逆向的 一脸蒙蔽。这样的话求逆序对真的就是 简单了很多了
先给一个逆向求 逆序数 二元的做法的代码

#include <bits/stdc++.h>using namespace std;typedef long long ll;#define lowbit(x) (x)&(-x)const int N =1e6+10;int n;    ll c[N];    void init() {memset(c,0,sizeof(c));}    ll sum(ll x)    {        ll ans=0;        while(x<=n+10)        {            ans+=c[x];            x+=lowbit(x);        }        return ans;    }    void change(ll x,ll y)    {        while(x)            c[x]+=y,x-=lowbit(x);    }int haifei[10000000],panting[1000000];int main(){    ll i,j;    while(cin>>n)    {        ll ans=0;        for(i=0;i<n;i++) scanf("%d",&haifei[i]),panting[i]=haifei[i];            init();        sort(haifei,haifei+n);        for(i=0;i<n;i++){            ll b=(lower_bound(haifei,haifei+n,panting[i])-haifei)+1;            ll siz=sum(b);            ans+=siz;            change(b,1);        }        cout<<ans<<endl;    }}

现在化作三元 大神的做法就是 用两个数组储存, y逆向数组存的是表示的是比 比它大的数 还有大的数的数量 而且是在逼它大的数前面出现的 这个怎么弄的。其实就是把每一次处理的时候,把比它大的数更新在y树状数组里,就可以处理了。 那么现在你要明确的是 y树状数组是用统计比 比它大的数 还有大的数的数量,更新操作的val是比他的数。
然后 x树状数组就是一个正常的树状数组,统计的是前面有多少比他大的数。。。虽然有点拗口。。但是可以简单的理解为在树状数组上套树状数组,那么就可以求 三元的,甚至四元的,再加一个树状数组呗

#include <bits/stdc++.h>using namespace std;typedef long long ll;#define lowbit(x) (x)&(-x)const int N =1e6+10;int n;struct node{    ll c[N];    void init() {memset(c,0,sizeof(c));}    ll sum(ll x)    {        ll ans=0;        while(x<=n+10)        {            ans+=c[x];            x+=lowbit(x);        }        return ans;    }    void change(ll x,ll y)    {        while(x)            c[x]+=y,x-=lowbit(x);    }}x,y;int haifei[10000000],panting[1000000];int main(){    ll i,j;    while(cin>>n)    {        ll ans=0;        for(i=0;i<n;i++) scanf("%d",&haifei[i]),panting[i]=haifei[i];            x.init(),y.init();        sort(haifei,haifei+n);        for(i=0;i<n;i++){            ll b=(lower_bound(haifei,haifei+n,panting[i])-haifei)+1;            ll siz=y.sum(b);            ans+=siz;            y.change(b,x.sum(b));            x.change(b,1);        }        cout<<ans<<endl;    }}
原创粉丝点击