題目描述
現在給出 1∼n 的乙個排列,按照某種順序依次刪除 m 個元素,你的任務是在每次刪除乙個元素之前統計整個序列的逆序對數。
輸入格式
第一行包含兩個整數 n和 m,即初始元素的個數和刪除的元素個數。
以下 n 行,每行包含乙個 1∼n 之間的正整數,即初始排列。
接下來 m 行,每行乙個正整數,依次為每次刪除的元素。
輸出格式
輸出包含 m 行,依次為刪除每個元素之前,逆序對的個數。
cdq分治求解動態逆序對,即在有刪除操作的情況下求逆序對數,出座標、數值外,把時間作為第三個維度,即可轉換為三維偏序問題。
把從前往後刪除轉換為從後往前增加,然後每加入乙個點,求兩部分,一部分座標小於值大於,另一部分座標大於值小於,關鍵點在於第三維,若要形成逆序對,時間這一維必須大於。相當於做了兩遍cdq分治。
參考有個地方要注意a[0][b[x]].x=a[1][b[x]].x=m+1-i;不是a[0][x].x=a[1][x].x=m+1-i;我調了一晚上這個bug。
#include
#define lowbit(x) x&(-x)
using
namespace std;
typedef long
long ll;
const ll maxn=
1e5+10;
ll tree[maxn]
;ll ans[maxn]
;ll b[maxn]
;struct nodea[2]
[maxn]
;bool
cmpx
(node a,node b)
bool
cmpy
(node a,node b)
void
update
(ll x,ll val)
}ll query
(ll x)
return sum;
}void
cdq(ll l,ll r,ll wc)
ll mid=
(l+r)
>
>1;
cdq(l,mid,wc)
;cdq
(mid+
1,r,wc)
;sort
(a[wc]
+l,a[wc]
+mid+
1,cmpy)
;sort
(a[wc]
+mid+
1,a[wc]
+r+1
,cmpy)
; ll j=l;
for(ll i=mid+
1;i<=r;i++
) a[wc]
[i].ans+
=query
(a[wc]
[i].z-1)
;}for(ll i=l;iintmain()
for(ll i=
1;i<=m;i++
)sort
(a[0]+
1,a[0]
+1+n,cmpx)
;sort
(a[1]+
1,a[1]
+1+n,cmpx)
;cdq(1
,n,0);
cdq(
1,n,1)
;for
(ll i=
1;i<=n;i++
) ans[0]
/=2;
for(ll i=
1;i<=m;i++
)for
(ll i=m;i>=
1;i--
)}
P3157 CQOI2011 動態逆序對
對於序列a,它的逆序對數定義為滿足iaj的數對 i,j 的個數。給1到n的乙個排列,按照某種順序依次刪除m個元素,你的任務是在每次刪除乙個元素之前統計整個序列的逆序對數。輸入格式 輸入第一行包含兩個整數n和m,即初始元素的個數和刪除的元素個數。以下n行每行包含乙個1到n之間的正整數,即初始排列。以下...
P3157 CQOI2011 動態逆序對
傳送門 設 val i 為位置 i 的值 維護 ansl i 表示位置 i 的數左邊所有大於 val i 的數的數量 維護 ansr i 表示位置 i 的數右邊所有小於 val i 的數的數量 考慮先求出一開始總的逆序對數 ans 每次刪除乙個數 位置為 p 就把 ans 減去 ansl p ans...
洛谷 P3157 CQOI2011 動態逆序對
對於序列a,它的逆序對數定義為滿足iaj的數對 i,j 的個數。給1到n的乙個排列,按照某種順序依次刪除m個元素,你的任務是在每次刪除乙個元素之前統計整個序列的逆序對數。可以值域分塊,塊套樹狀陣列,樹套樹 不過用序列分塊 vector 一樣能水過這道題 考慮刪去乙個點 x 對答案產生的影響,拿下面的...