1. 程式人生 > >hdu2688 Rotate(樹狀數組)

hdu2688 Rotate(樹狀數組)

cst article owb ref lan 長度 -s ble show

題目鏈接:點擊打開鏈接

題意描寫敘述:對一個長度為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;
}


hdu2688 Rotate(樹狀數組)