題意:給你兩個均有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 ...