zoukankan      html  css  js  c++  java
  • XJTUOJ wmq的队伍(树状数组求 K 元逆序对)

    题目链接:http://oj.xjtuacm.com/problem/14/【分析】二元的逆序对应该都会求,可以用树状数组。这个题要求K元,我们可以看成二元的。我们先从后往前求二元逆序对数,

     然后对于每一个数就可以求出在这个数后面的比他小的数的数量。然后我们再加一元时,当前扫到a[i],那么在树状数组中,对于那些比他大的数的 逆序对数+=上一元a[i]的逆序对数。

    #include <bits/stdc++.h>
    #define met(a,b) memset(a,b,sizeof a)
    #define pb push_back
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define lowbit(x) (x&(-x))
    using namespace std;
    typedef long long ll;
    ll mod = 1e9+7;
    const int N=2e4+50;
    const int M=N*N+10;
    int n,m,k,a[N];
    ll tre[N],ans1[N],ans2[N];
    void add(int x,ll s){
        while(x<=n){
            tre[x]+=s;
            tre[x]%=mod;
            x+=lowbit(x);
        }
    }
    ll Sum(int x){
        ll ret=0;
        while(x>0){
            ret+=tre[x];
            ret%=mod;
            x-=lowbit(x);
        }
        return ret;
    }
    int main() {
        int u,v;
        int T;
        scanf("%d",&T);
        while(T--){
            scanf("%d%d",&n,&k);
            for(int i=1;i<=n;i++)scanf("%d",&a[i]),ans2[i]=1;
            if(m==1){
                printf("%d
    ",n);continue;
            }
            for(int t=2;t<=k;t++){
                for(int i=1;i<=n;i++)ans1[i]=ans2[i],ans2[i]=tre[i]=0;
                for(int i=n;i>=1;i--){
                    ans2[a[i]]=Sum(a[i]);
                    add(a[i],ans1[a[i]]);
                }
            }
            ll ans=0;
            for(int i=1;i<=n;i++)ans=(ans+ans2[i])%mod;
            printf("%lld
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    第一阶段-坑爹猴
    终于做出来了
    一天就制作成了这些
    累成狗做出来的
    一周的学习,组合起来的成就
    刚刚出炉的搜狗浏览器最新版本
    自己动手设计了一下下百度首页
    数论:卢卡斯定理(求组合数)
    数据结构:ST表模板(可维护区间RMQ)
    快读和快写(可以使用__int128)
  • 原文地址:https://www.cnblogs.com/jianrenfang/p/6710162.html
Copyright © 2011-2022 走看看