zoukankan      html  css  js  c++  java
  • 珂朵莉的数列

    题目链接:https://ac.nowcoder.com/acm/problem/14522

    思路: 求区间内逆序对个数,可以找出逆序对之后求它对整个区间的贡献。 例如 j,k是一个逆序对,那么它对整个区间的贡献应该是(j-0)*(n-k+1),因此,用树状数组枚举k,找出(1~k-1)范围内大于a[k]的数的坐标和就行了。

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <string>
    #include <stack>
    #include <queue>
    #include <cmath>
    #define ll long long
    #define pi 3.1415927
    #define inf 0x3f3f3f3f
    #define mod 1000000007
    using namespace std;
    ll n,m;
    ll a[1000005],b[1000005],c[1000005];
    ll lowbit(ll i)
    {
        return i&-i;
    }
    void add(ll i,ll p)  //这里是将坐标加上去,求前i项的坐标和
    {
        while (i<=n)
        {
            c[i]+=p;
            i+=lowbit(i);
        }
    }
    ll getsum(ll k)
    {
        ll res=0;
        while(k)
        {
            res+=c[k];
            k-=lowbit(k);
        }
        return res;
    }
    void Print(__int128_t x)  //__int128_t 输出方法
    {
        if(x==0)
            return ;
        Print(x/10);
        putchar(x%10+'0');
    }
    int main ()
    {
        ll T,i,t,j,k,p;
        cin>>n;
        for(i=1;i<=n;++i)
            scanf("%lld",&a[i]),b[i]=a[i];
        //先排序,之后二分,在a[i]中存的是第i个数的大小的位置
        sort(b+1,b+n+1);
        for(i=1;i<=n;++i)
            a[i]=lower_bound(b+1,b+n+1,a[i])-b;
        __int128_t sum=0;
        for(i=1;i<=n;++i)
        {
            sum+=(getsum(n)-getsum(a[i]))*(n-i+1);
            add(a[i],i);
        }
        if(sum==0)
            cout<<"0";
        else
            Print(sum);
        cout<<endl;
        return 0;
    }
  • 相关阅读:
    [模板] 主席树
    [模板] 替罪羊树
    [模板] Treap
    [LUOGU] P4342 [IOI1998]Polygon
    [JOYOI] 1051 选课
    poj 1845 数论(唯一分解定理+分治法求等比数列前n项的和mod m的值)
    poj 2418 bst统计字符串
    hdu 3791 二叉排序树
    hdu 3999 二叉排序树
    toj 3711 水题
  • 原文地址:https://www.cnblogs.com/blowhail/p/13266593.html
Copyright © 2011-2022 走看看