Balanced Photo(USACO)

题目大意:

我们有一个数列,数列中有n个数,对于一个数ai,在它左边的比他大的数的个数为li,右边比他大的数的个数为ri,若li,ri中的较大者比较小者的两倍还大,那么他就是一个不平衡数,求不平衡数的数量。

————————————————我是分割线————————————————

好吧,典型逆序对。

因为我们要求左边比他大的数的个数,所以我们倒着排序,然后再离散。

然后树状数组解决问题。

那么右边怎么办?

很显然我们得到的离散数组的值就是比他大的数的个数+1(它本身),所以右边的答案为:离散数组值-左边比他大的数的个数-1;

然后轻松统计答案

下面贴代码

#include<cstdio>
#include<algorithm>
#define MN 100005
using namespace std;
int n,tot;
int b[MN],t[MN];
struct qaq{
    int num,opt;
}a[MN];
int lowbit(int x){return (x&-x);}
int query(int x)
{
    int ans=0;
    while(x)
    {
        ans+=t[x];
        x-=lowbit(x);
    }
    return ans;
}
void update(int x){
    while(x<=n)
    {
        t[x]++;
        x+=lowbit(x);    
    }
}
bool cmp(qaq a,qaq b){return a.num>b.num;}
int main(){
//    freopen(".in","r",stdin);
//    freopen(".out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i].num),a[i].opt=i;
    sort(a+1,a+n+1,cmp);
    for(int i=1;i<=n;i++)b[a[i].opt]=i;
    for(int i=1;i<=n;i++)
    {
        int l=query(b[i]),r=b[i]-l-1;
        if ((l*2<r)||(r*2<l))tot++;
        update(b[i]);
    }
    printf("%d\n",tot);
//    fclose(stdin);
//    fclose(stdout);
}

 

posted @ 2017-06-16 15:03  ghostfly233  阅读(188)  评论(0编辑  收藏  举报