計蒜客模擬賽D2T2 蒜頭君的排序:區間逆序對(移動端點) + 樹狀陣列

Leohh發表於2017-07-31

題目連結:https://nanti.jisuanke.com/t/16443

題意:

  給你一個由1~n構成的正整數序列,有m組詢問,每組詢問要求輸出[l , r]區間內的逆序對個數。

資料範圍:

  對於100%的資料,滿足1 <= n,m <= 30000,l < r,∑ | l[i] - l[i-1] | + ∑ | r[i] - r[i-1] | <= 7 * 10^6。

 

題解:

  如果知道區間[l , r]中的逆序對個數,那麼也可以快速求出區間[l-1 , r],[l+1 , r],[l , r-1],[l , r+1]的逆序對個數。

  ① [l-1 , r]的個數 = [l , r]的個數 + [l , r]中比a[l-1]小的元素的個數

  ② [l+1 , r]的個數 = [l , r]的個數 - [l+1 , r]中比a[l]小的元素的個數

  ③ [l , r-1]的個數 = [l , r]的個數 - [l , r-1]中比a[r]大的元素的個數

  ④ [l , r+1]的個數 = [l , r]的個數 + [l , r]中比a[r+1]大的元素的個數

  查詢區間內比x大(小)的元素的個數用樹狀陣列實現。

  比x大的元素個數 = query(x - 1)

  比x小的元素個數 = query(n) - query(x)  (區間內元素總個數減去大於等於x的元素個數)

  先假定現在的區間為[1 , 1],逆序對總個數為0。對於每一組詢問,只要不斷移動當前區間的左右端點,並同時更新答案,直至當前區間與詢問區間相同即可,輸出sum值。

 

AC Code:

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 #define MAX_N 30005
 5 
 6 using namespace std;
 7 
 8 int n,m;
 9 int a[MAX_N];
10 int dat[MAX_N];
11 
12 void update(int k,int a)
13 {
14     while(k<=n)
15     {
16         dat[k]+=a;
17         k+=k&-k;
18     }
19 }
20 
21 int query(int k)
22 {
23     int sum=0;
24     while(k>0)
25     {
26         sum+=dat[k];
27         k-=k&-k;
28     }
29     return sum;
30 }
31 
32 void read()
33 {
34     cin>>n;
35     for(int i=1;i<=n;i++)
36     {
37         cin>>a[i];
38     }
39 }
40 
41 void solve()
42 {
43     memset(dat,0,sizeof(dat));
44     cin>>m;
45     int sum=0;
46     int lef=1,rig=1;
47     update(a[1],1);
48     for(int i=0;i<m;i++)
49     {
50         int l,r;
51         cin>>l>>r;
52         while(lef<l)
53         {
54             update(a[lef],-1);
55             sum-=query(a[lef]-1);
56             lef++;
57         }
58         while(lef>l)
59         {
60             lef--;
61             sum+=query(a[lef]-1);
62             update(a[lef],1);
63         }
64         while(rig<r)
65         {
66             rig++;
67             sum+=query(n)-query(a[rig]);
68             update(a[rig],1);
69         }
70         while(rig>r)
71         {
72             update(a[rig],-1);
73             sum-=query(n)-query(a[rig]);
74             rig--;
75         }
76         cout<<sum<<endl;
77     }
78 }
79 
80 int main()
81 {
82     read();
83     solve();
84 }

 

相關文章