bzoj3295 CQOI2011 動態逆序對

2022-04-07 11:40:27 字數 1300 閱讀 4688

time limit:10 secmemory limit:128 mb

submit:3122solved:986對於序列a,它的逆序對數定義為滿足iaj的數對(i,j)的個數。給1到n的乙個排列,按照某種順序依次刪除m個元素,你的任務是在每次刪除乙個元素之前統計整個序列的逆序對數。

輸入第一行包含兩個整數n和m,即初始元素的個數和刪除的元素個數。以下n行每行包含乙個1到n之間的正整數,即初始排列。以下m行每行乙個正整數,依次為每次刪除的元素。  

輸出包含m行,依次為刪除每個元素之前,逆序對的個數。

5 4153

4251

4252

21樣例解釋

(1,5,3,4,2)(1,3,4,2)(3,4,2)(3,2)(3)。

n<=100000 m<=50000

方法一:各種樹套樹,目測**難度較大

方法二:cdq分治+樹狀陣列

將刪除操作逆向,轉化成新增操作。

於是問題轉化成每次向序列中新增乙個數,詢問逆序對數。

考慮每次加入乙個數對答案的影響,它會與前面並且大於它的數和後面並且小於它的數構成逆序對。

然後在cdq分治裡做兩次就可以了。

#include

#include

#include

#include

#include

#include

#define f(i,j,n) for(int i=j;i<=n;i++)

#define d(i,j,n) for(int i=j;i>=n;i--)

#define ll long long

#define maxn 100005

using namespace std;

int n,m,pos[maxn],c[maxn],sl[maxn],sr[maxn];

ll ans[maxn];

struct dataa[maxn],b[maxn];

inline int read()

while (ch>='0'&&ch<='9')

return x*f;

}inline void add(int x,int y)

inline int query(int x)

inline void cdq(int l,int r)

f(i,l,r) a[i]=b[i];

tmp=l;

f(i,mid+1,r)

f(i,tmp+1,mid) add(a[i].v,-1);

cdq(l,mid);cdq(mid+1,r);

}int main()

bzoj3295 CQOI2011 動態逆序對

time limit 10 sec memory limit 128 mb submit 3122 solved 986 submit status discuss 對於序列a,它的逆序對數定義為滿足i aj 的數對 i,j 的個數。給1到n的乙個排列,按照某種順序依次刪除m個元素,你的任務是在每次...

Cqoi2011 BZOJ3295 動態逆序對

對於序列a,它的逆序對數定義為滿足i 樹狀陣列 一看到逆序對就要想到樹狀陣列。維護每個數前面到目前有多少個比自己大。動態的思路 因為要動態維護,每次只刪掉乙個數在逆序對中的貢獻 及每個數前面有多少個比自己大,每個數後面有多少數比自己小。先預處理出每個數前面有多少個比自己大ll i 每個數後面有多少個...

bzoj3295 Cqoi2011 動態逆序對

傳送門 題解 cdq分治 我們仔細想一想維護逆序對的時候我們用的不就是歸併排序嗎?而歸併排序不就可以看作一種分治嗎?於是此題走上正軌,我們可以用分治來寫 怎麼寫?我們刪除乙個點,損失了什麼?1.這個點x之前比我大的個數記為big x 這個點x之後比我小的記作small x 那麼損失 small x ...