hdu5497(树状数组模板)

用两个树状数组维护前缀后缀的值即可,必须离散化,否则TLE


参考代码:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<sstream>
#include<string>
#include<bitset>
using namespace std;

typedef long long LL;

const LL LINF = (1LL <<63);
const int INF = 1 << 31;


const int NS = 100010;
const int MS = 19;
const LL MOD = 1000000007;

struct BIT{
    int len;
    int c[NS];

    int lowbit(int x)
    {
        return (x & (-x));
    }

    void init(int _len)
    {
        len = _len;
        memset(c, 0, sizeof(c));
    }

    LL sum(int x)
    {
        LL ret=0;
        while(x > 0)
        {
            ret += c[x];
            x -= lowbit(x);
        }
        return ret;
    }

    LL sum(int l, int r)
    {
        LL ret=sum(r);
        if(l > 0)
        {
            ret -= sum(l - 1);
        }
        return ret;
    }

    void add(int x, int value)
    {
        while(x <= len)
        {
            c[x] += value;
            x += lowbit(x);
        }
    }
}suf, pre;

int n,m;
int a[NS];
int shine[NS];
map<LL, LL> mp;

int main()
{
//#ifndef ONLINE_JUDGE
//    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
//#endif

    int T;
    scanf("%d", &T);
//    cin >> T;
    while(T--)
    {
        scanf("%d %d", &n, &m);
//        cin >> n;

        for(int i = 1; i <= n; i++)
        {
//            cin >> a[i];
            scanf("%d", &a[i]);
            shine[i - 1] = a[i];
        }
        sort(shine, shine + n);
        int num = unique(shine, shine + n) - shine;

        for(int i = 1; i <= n; i++)
        {
            a[i] = lower_bound(shine, shine + num,a[i]) - shine + 1;
        }

        LL presum = 0;
        LL sufsum = 0;
        pre.init(num);
        suf.init(num);

        for(int i = n; i > m; i--)
        {
            int v = a[i];
            sufsum += suf.sum(v - 1);
            suf.add(v, 1);
        }
        LL minv = presum + sufsum;
   //     cout<<"i = "<<0<<" min = "<<minv<<" presum = "<<presum<<" sufsum = "<<sufsum<<endl;

        for(int i = 1; i + m <= n; i++)
        {
            int v = a[i];
            presum += pre.sum(v + 1, num);
            presum += suf.sum(1, v - 1);
            pre.add(v, 1);

            v = a[i + m];
            sufsum -= suf.sum(1, v - 1);
            sufsum -= pre.sum(v + 1, num);
            suf.add(v, -1);

            minv = min(minv, presum + sufsum);

    //    cout<<"i = "<<i<<" min = "<<minv<<" presum = "<<presum<<" sufsum = "<<sufsum<<endl;
        }
        printf("%I64d\n", minv);
//        cout<<minv<<endl;
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值