BZOJ3295 Cqoi2011 動態逆序對

2021-08-01 13:51:11 字數 1898 閱讀 3207

bzoj3295

刪除好像挺麻煩的。。那就考慮倒一下,也就是倒序加值。

考慮乙個值加入進來,對答案的影響就是,它左邊的比它大的個數和它右邊比它小的個數加和。

先只考慮一半。只考慮右邊比它小的數的個數。那麼假設當前加入的為乙個三元組 (t

,pos

,x) ,表示時間,位置和值。那麼就是求滿足(t

tppos

>po

s,xx

的三元組(t

t,pp

os,x

x)的個數。(因為把刪除操作反過來進行了所以就是tt

<

t )。

那麼三維偏序就可以考慮用cd

q 分治。

當然這只完成了一半啦,剩下的一半其實也相同。

我偷了點懶。。想只寫一遍cd

q 。另外一半操作的時候,把位置和值都顛倒了一下。也就是原本應該插入的是15

342 ,變成了42

315 。那麼相當於每次也是求右邊的比它小的個數啦。

對應到**中:第一次操作是

for(int i=1;i

<=n;i++) if(!flag[i]) q[++tot]=query(0,pos[i],i,0);

for(int i=m;i;i--)

後面一遍操作寫成:

for(int i=1;i

<=n;i++) if(!flag[i]) q[++tot]=query(0,n-pos[i]+1,n-i+1,0);

for(int i=m;i;i--)

warning!

相同的位置應先查詢再修改。 要開l

ongl

ong . do

n′tf

orge

t 要求出刪完的序列中逆序對的個數!

#include 

#include

#include

#define n 100005

#define m 200005

using

namespace

std;

typedef

long

long ll;

int read()

while(isdigit(ch))

return x*f;

}int n,m,tot;

int a[n],b[n],pos[n];

ll szsz[n],ans[n],preans;

bool flag[n];

class query

query(int tt,int pp,int xx,int ii)

}q[m],tmp[m];

bool

operator

<(query a,query b)

int lowbit(int x)

void sum_up(int x,int y)

ll query(int x)

void clear(int x)

void input_init()

}int st[n],top;

void get_preans()

for(int i=1;i<=top;i++) clear(st[i]);

}bool judge(query a,query b)

void cdq(int l,int r)

else

}while(p<=mid) tmp[o++]=q[p++];

while(q<=r)

for(int i=0;ivoid re_make()

}void solve()

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 ...