hdu2688 Rotate(樹狀數組)
阿新 • • 發佈:2017-06-10
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(樹狀數組)