• COGS 859. 数列


    /*
    先来说一下第一眼看到想出的奇葩方法23333..
    找每个数左右有几个比他小的
    前几天刚学了区间第k小的求法
    然后...
    枚举中间的那个点 对于左区间 二分找到他是第几大 右区间同理
    然后  *起来 
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define maxn 50010
    #define maxm 50010*18*5
    #define ll long long
    using namespace std;
    ll n,cnt,root[maxn],order[maxn],a[maxn],ans;
    struct node{
        ll lc,rc,sum;
    }t[maxm];
    ll init(){
        ll x=0;char s=getchar();
        while(s<'0'||s>'9')s=getchar();
        while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
        return x;
    }
    ll Build(ll S,ll L,ll R){
        ll k=++cnt;t[k].sum=S;
        t[k].lc=L;t[k].rc=R;
        return k;
    }
    void Insert(ll &root,ll pre,ll pos,ll l,ll r){
        root=Build(t[pre].sum+1,t[pre].lc,t[pre].rc);
        if(l==r)return;
        ll mid=l+r>>1;
        if(pos<=mid)Insert(t[root].lc,t[pre].lc,pos,l,mid);
        else Insert(t[root].rc,t[pre].rc,pos,mid+1,r);
    }
    ll Query(ll L,ll R,ll k,ll l,ll r){
        if(l==r)return l;
        ll sum=t[t[R].lc].sum-t[t[L].lc].sum;
        ll mid=l+r>>1;
        if(k<=sum)return Query(t[L].lc,t[R].lc,k,l,mid);
        else return Query(t[L].rc,t[R].rc,k-sum,mid+1,r);
    }
    int main()
    {
        //freopen("queueb.in","r",stdin);
        //freopen("queueb.out","w",stdout);
        n=init();
        for(ll i=1;i<=n;i++){
            a[i]=init();
            order[i]=a[i];
        }
        sort(order+1,order+1+n);
        ll num=n,pos,l,r,x,s1,s2;
        for(ll i=1;i<=n;i++){
            pos=lower_bound(order+1,order+1+n,a[i])-order;
            Insert(root[i],root[i-1],pos,1,num);
        }
        for(ll i=1;i<=n;i++){
            x=a[i];s1=s2=0;
            l=1;r=i;
            while(l<=r){
                ll mid=l+r>>1;
                pos=Query(root[0],root[i],mid,1,num);
                if(order[pos]<x){
                    s1=mid;l=mid+1;
                }
                else r=mid-1;
            }
            l=1;r=n-i+1;
            while(l<=r){
                ll mid=l+r>>1;
                pos=Query(root[i-1],root[n],mid,1,num);
                if(order[pos]<x){
                    s2=mid;l=mid+1;
                }
                else r=mid-1;
            }
            ans+=s1*s2;
        }
        printf("%lld
    ",ans);
        return 0;
    }
    /*
    其实求左右各有几个比他小的 可以用树状数组
    逆序对是求左边几个比他大的这个一样啊
    注意右边的时候离散化排序和左边不一样 
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define maxn 50010
    #define ll long long
    using namespace std;
    int n,b[maxn],t[maxn],l[maxn],r[maxn];
    ll ans;
    struct node{
        int o,x;
    }a[maxn];
    int init(){
        int x=0;char s=getchar();
        while(s<'0'||s>'9')s=getchar();
        while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
        return x;
    }
    int cmp1(const node &a,const node &b){
        if(a.x==b.x)return a.o>b.o;
        return a.x<b.x;
    }
    int cmp2(const node &a,const node &b){
        if(a.x==b.x)return a.o<b.o;
        return a.x<b.x;
    }
    void Add(int pos,int data){
        while(pos<=n){
            t[pos]+=data;
            pos+=pos&(-pos);
        }
    }
    int find(int pos){
        int r=0;
        while(pos){
            r+=t[pos];
            pos-=pos&(-pos);
        }
        return r;
    }
    int main()
    {
        freopen("queueb.in","r",stdin);
        freopen("queueb.out","w",stdout);
        n=init();
        for(int i=1;i<=n;i++){
            a[i].x=init();
            a[i].o=i;
        }
        sort(a+1,a+1+n,cmp1);
        for(int i=1;i<=n;i++)
            b[a[i].o]=i;
        for(int i=1;i<=n;i++){
            Add(b[i],1);
            l[i]=find(b[i]-1);
        }
        memset(t,0,sizeof(t));
        sort(a+1,a+1+n,cmp2);
        for(int i=1;i<=n;i++)
            b[a[i].o]=i;
        for(int i=n;i>=1;i--){
            Add(b[i],1);
            r[i]=find(b[i]-1);
        }
        for(int i=1;i<=n;i++)
            ans+=(ll)l[i]*r[i];
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    什么是UDDI?
    保存图片
    什么是EIP?
    众多Android开源项目推荐
    Google code android 开源项目 集合
    实现屏幕下方展示的TAB分页
    Android中attr 自定义 属性详解
    J2EE快速开发框架wabacus
    popwindow动画显示消失,activity切换动画
    Android 一些项目的源代码,覆盖Android开发的每个领域
  • 原文地址:https://www.cnblogs.com/yanlifneg/p/5851337.html
Copyright © 2020-2023  润新知