hdu2688 Rotate(树状数组)

题目链接:点击打开链接

题意描述:对一个长度为2<=n<=3000000的数组,求数组中有序对(i<j并且F[i]<F[j])的数量?其中数组元素F[i]范围(0<F[i]<=10000),现有m<10000个操作

操作一:R x y(其中y-x<=1000)将数组x~y之间的元素旋转

操作二:Q查询当前数组中含有的有序对的数量


解题思路:

1、先求的原始数组中有序对的总数量(如果直接求,则时间复杂度为O(n*10000);如果使用树状数组时间复杂度为O(nlgn))即O(n*14)

2、对于每次操作一,循环遍历F[x+1]~F[y]中元素与F[x]的关系,对总数量进行加减即可O(1000*m)

3、对于操作二,直接输出总数量即可(O(1))


代码:

#include <cstdio>
#include <cstring>
#define MAXN 3000010
using namespace std;
int d[MAXN];
int C[10010];
int n,m;
int lowbit(int x)
{
    return x&(-x);
}
int sum(int pos)
{
    int res=0;
    while(pos>0)
    {
        res+=C[pos];
        pos-=lowbit(pos);
    }
    return res;
}
void add(int pos,int v)
{
    while(pos<=10000)
    {
        C[pos]+=v;
        pos+=lowbit(pos);
    }
}
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        memset(C,0,sizeof(C));
        long long ans=0;
        for(int i=0; i<n; i++)
        {
            scanf("%d",&d[i]);
            add(d[i],1);
            ans+=sum(d[i]-1);
        }
        scanf("%d",&m);
        char st[10];
        for(int i=1; i<=m; ++i)
        {
            scanf("%s",st);
            switch(st[0])
            {
            case 'Q':
                printf("%I64d\n",ans);
                break;
            case 'R':
                int l,r;
                scanf("%d%d",&l,&r);
                int v=d[l];
                for(int j=l+1; j<=r; j++)
                {
                    if(d[j]>v) ans--;
                    else if(d[j]<v) ans++;
                    d[j-1]=d[j];
                }
                d[r]=v;
                break;
            }
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值