CQOI2011 動態逆序對

2021-08-19 19:07:44 字數 1400 閱讀 4949

這是一道cdq分治的好題,這道題的前置知識是cdq分治解決三維偏序問題,如果不會這個話請先自行學習。

首先第乙個答案很顯然就是逆序對的數量,然後後面每次的刪除操作,我們考慮把這個被刪除的點原先的貢獻從答案中拿掉。我們用y表示這個點的數,del表示第幾個被刪除,若沒有被刪除則del=m+1

考慮每個點的貢獻分為兩種。

1.在我前面,y和del均比我大

2.在我後面,y比我小,del比我大

因為沒有刪除的點不會對答案有影響,所以del設為m+1就行了。

而del比我小的點在刪除它的時候已經把貢獻減掉了,所以不能重複算

那麼我們發現這兩個就是非常典型的三維偏序問題,用cdq解決就行了,可以看**

#include

#include

#include

#include

#include

#include

#define ll long long

#define inf (2139062143)

#define n (100001)

using namespace std;

int n,m;

ll ans;

int d[n],t[n],fnd[n];

struct nodea[n],q[n],f[n];

template void read(t&t)

do while (isdigit(p));

if (!fl) t=-t;

}void add(int

x)void sub(int x)

void add1(int

x)void sub1(int

x)int query(int

x)void cdq1(int l,int r)

else

}for (int i=l;i<=mid;i++) sub(q[i].del);

for (int i=l;i<=r;i++) q[i]=f[i];

}void cdq2(int l,int r)

else

}for (int i=mid+1;i<=r;i++) sub(a[i].del);

for (int i=l;i<=r;i++) a[i]=f[i];

}signed main()

for (int i=1;i<=n;i++)

for (int i=1;i<=n;i++) a[i].del=m+1;

for (int i=1;i<=m;i++)

memcpy(q,a,sizeof(q));

cdq1(1,n);

cdq2(1,n);

for (int i=1;i<=m;i++)

return

0;}

Cqoi2011 動態逆序對

主席樹套樹狀陣列。主席樹第一題。鏈結靜態的逆序對問題很簡單,用線段樹或者是樹狀陣列即可解決。現在的問題是如何解決一道動態的逆序對問題?我們先把所有的逆序對統計出來。每次刪除數,我們可以把這個數對於逆序對個數的貢獻刪除出去。這個貢獻如何統計呢?front i 記錄i位置之前有多少個數比這個數大 bac...

CQOI2011 動態逆序對

點此看題 考慮c dq cdqcd q,有三個值 t,d,v t,d,v t,d,v 要求t i t iti d i d idi v i vj v i v j vi vj 很容易看出來是三維偏序的板題,我們先保證t tt的有序,cdq cdqcd q的時候排序d dd,然後用樹狀陣列查詢v vv,貼...

CQOI2011 動態逆序對

使用樹狀陣列求出初態下出f i g i 表示位置小 大 於i且值大 小 於a i 的元素個數。顯然ans 初 sum f i sum g i 考慮第乙個刪去的點x,刪去以後,ans減少f x g x 再考慮第二個刪去的點y,刪去以後,ans減少f y g y 不,f y g y 中可能算上了x 此題...