HDU1899 Sum the K-th's(树状数组)

枚举,每次增加点,删除点

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include< string>
#include<algorithm>
#include<map>
#include<queue>
#include<vector>
#include<cmath>
#include<utility>
using  namespace std;
typedef  long  long LL;
const  int N =  100008, INF =  0x3F3F3F3F, MOD =  1000000007 ;
#define MS(a, num) memset(a, num, sizeof(a))
int C[N];
int n, m, k;
int a[N], rak[N];

struct data{
     int num, i;
}b[N];
inline  int lowbit( int x){
     return x&-x;
}
inline  void add( int x,  int val){ // 将第x个数增加val,从1计数
     for( int i=x;i<=n;i+=lowbit(i)){
        C[i] += val;
    }
}
inline  int sum( int x){ // 求1到x的和
     int ret =  0;
     for( int i=x;i> 0;i-=lowbit(i)){
        ret+=C[i];
    }
     return ret;
}


bool cmp( const data &a,  const data &b){
     return a.num < b.num;
}


int getK( int val){
     int l =  1, r = n +  1;
     while(l < r){
         int m = (l + r)>> 1;
         int s = sum(m);
         if(s < k){
            l = m +  1;
        } else{
            r = m;
        }
    }
     return b[l - 1].num;
}
int main(){
     int t;
    cin>>t;
     while(t--){
        scanf( " %d %d %d ", &n, &m, &k);
         for( int i =  0; i < n; i++){
            scanf( " %d ", &a[i]);
            b[i].num = a[i];
            b[i].i = i;
        }
        MS(C,  0);
        sort(b, b + n, cmp);

         for( int i =  0; i< n; i++){
            rak[b[i].i] = i +  1;
        }

        LL ans =  0;
         for( int i =  0; i < m; i++){
            add(rak[i % n],  1);
        }

         for( int i = m +  1; i <  2 * m +  1 ;i++){
            add(rak[i % n],  1);
        }

         for( int i = m ; i <= m + n - 1 ; i++){
            ans += getK(a[i % n]);
            ans %= MOD;
             if(i != m + n - 1 ){
                add(rak[(i - m)%n], - 1);
                add(rak[(i + m +  1) % n],  1);
                add(rak[i % n],  1);
                add(rak[(i +  1) % n], - 1);
            }
        }
        printf( " %I64d\n ", ans % MOD);
    }
     return  0;

} 

转载于:https://www.cnblogs.com/IMGavin/p/5708417.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值