cf 1187D 逆序對(線段樹)

2021-09-24 23:21:21 字數 1630 閱讀 6800

題意:給你兩個均有n個數的陣列,現在你可以對a陣列中的任意區間進行sort操作,問你在sort完之後能不能得到b陣列。

做法:這個是真的想不到啊。。想法2200分的題目,大概的意思就是,因為可以對其中的任意區間進行操作,等於是去找逆序對的樣子,for每個數,當前數字在原陣列位置前不能有更小的未被消去的值,如果這個數合法,則這個位置被消去,什麼意思呢。假設我們有陣列 3 1 2 要變成1 3 2 ,那麼對於1來說,原來的位置2及之前沒有更小的數字,那麼就變到這個位置就是合法的,3是位置1,也是合法的,但是如果要從3 1 2 變成 3 2 1  那麼對於3來說是合法的,但是對於2來說,原來的第三個數字之前還有未被消去的1是最小值,比它本身小,那麼就不合法,換句話說,就是原來比自己小的數在變換之後跑到了自己後面去,那麼就是no了。

#include #define lson rt<<1

#define rson rt<<1|1

#define rep(i,a,b) for(int i=a;i<=b;i++)

using namespace std;

typedef long long ll;

const int maxn=300005;

const int inf=400005;

int mi[maxn<<2],n,a[maxn];

int b[maxn],cka[maxn],ckb[maxn];

queueq[maxn];

void build(int l,int r,int rt)

int mid=(l+r)/2;

build(l,mid,lson);

build(mid+1,r,rson);

mi[rt]=min(mi[lson],mi[rson]);

}void update(int l,int r,int rt,int pos,int v)

int mid=(l+r)/2;

if(pos<=mid) update(l,mid,lson,pos,v);

else update(mid+1,r,rson,pos,v);

mi[rt]=min(mi[lson],mi[rson]);

}int query(int l,int r,int rt,int ql,int qr)

int mid=(l+r)/2;

int ret=inf;

if(ql<=mid) ret=min(ret,query(l,mid,lson,ql,qr));

if(qr>mid) ret=min(ret,query(mid+1,r,rson,ql,qr));

return ret;

}int main()

rep(i,1,n)

sort(cka+1,cka+1+n); sort(ckb+1,ckb+1+n);

bool ok=true;

rep(i,1,n)

if(!ok)

build(1,n,1);

rep(i,1,n)

rep(i,1,n)

update(1,n,1,rr,inf);

}if(!ok) printf("no\n");

else printf("yes\n");

}  return 0;

}

逆序對 線段樹解法

逆序對 線段樹解法 求逆序對問題是乙個十分經典的演算法問題,通常使用歸併排序解決,經gster大神指點,寫出了逆序對線段樹寫法,順便練了練線段樹。題目傳送門 1 2 segment tree 3author shhhs 42016 09 28 12 35 17 5 6 include bits st...

求逆序對(線段樹版)

乙個序列a1,a2,a3.an,求出滿足 ai aj 且 i j 的個數。乙個最容易想到的方法就是列舉所有的i,j看看是否滿足,顯然是o n 2 的複雜度。不夠好。可以這樣考慮,開乙個陣列儲存這n個數出現的位置和對應的次數,這個陣列要開到a陣列裡最大的那個數max,也就是hash,初始狀態陣列裡沒有...

hdu 1394 (最小逆序對 線段樹

題意 給n個0到n 1的數,每次可以取乙個放後面,求最小逆序對 思路 求逆序對可以利用樹狀陣列或者線段樹元素出現的時間差來維護,這裡由於n個數是0到n 1,所以每次更新就是加上原來的順序對,減去逆序對,就是 n 1 2 a i include include include define lson ...