洛谷P3960 NOIP2017 列隊

2022-05-13 12:01:53 字數 1722 閱讀 5005

資料結構題還是挺好玩的

注意到每次只變動三個點:(x,y),(x,m),(n,m),其他地方都是整塊移動。

可以開n+1個線段樹,前n個存每行前m-1個人,最後乙個存第m列的人。

(x,y)位置的人出列時,抽出該位置的標號,加到第n+1個線段樹的最後面去,抽出第n+1個線段樹的第x個元素(即(x,m),加到第x個線段樹的最後面去。

↑實現這一操作,可以記線段樹的size,每次二分查詢樹上第k個元素即可確定位置。

↑當然樹不可能全建出來,需要動態開點。尚未申請的結點,size直接用$ r-l+1 $計算。

寫到一半想到不需要專門抽出來,只需要記錄該行到該位置為止抽出過a個數,找(x,y)時實際找(x,y+a)即可。可以開個vector什麼的存新加到隊伍最右邊的人。

這樣的話更加方便&優美,而且可以用樹狀陣列寫,**量也減小了。

但是看著自己寫了一大半的**不捨得丟,還是強行按原計畫敲完了。

————

老年退役選手連noip題都做不來了。做這題成功遇到了陣列開小,變數寫混,初始化錯誤,輸出錯誤等等問題,調了好久。

不開心qaq

————

1 #include2 #include3

#define ll long long

4using

namespace

std;

5const

int mxn=800010;6

struct

nodet[mxn<<3

];10

int cnt=0,mod=0;11

introot[mxn];

12int

n,n,m,q;

13 inline int getsz(int l,int r,int

rt)17

void pushup(int l,int r,int

rt)25

intanspos;

26int query(int k,int l,int r,int &rt)

31if(l==r)

36 anspos=l;

37return

rt;38}39

int mid=(l+r)>>1,tmp=getsz(l,mid,t[rt].lc);

40if(k<=tmp)

41return

query(k,l,mid,t[rt].lc);

42else

return query(k-tmp,mid+1

,r,t[rt].rc);43}

44void update(ll v,int p,int l,int r,int &rt)

49if(l==r)

54else t[rt].sz=1;55

return;56

}57int mid=(l+r)>>1;58

if(p<=mid)update(v,p,l,mid,t[rt].lc);

59else update(v,p,mid+1

,r,t[rt].rc);

60pushup(l,r,rt);

61return;62

}63void info(int l,int r,int

rt)72

intmain()

90else

113//

info(1,n,root[n+1]);

114}

115return0;

116 }

洛谷P3953 NOIp2017 逛公園

考慮到邊權可能為 0 轉移的順序會影響最後的結果,因此我們用記憶化搜尋代替直接dp 0 環 如何判斷乙個點 u是否在滿足條件的路徑上?顯然我們可以知道這個點滿足di s1 u di sn u di s1 n k 我們把所有長度為 0 的邊建成乙個新圖,然後用ta rjan 找出所有點數大於 1 的強...

洛谷P3960 列隊(Splay)

傳送門 感覺自己好久不打資料結構已經完全不會了orz 據說正解樹狀陣列?然而並不會 首先考慮一下每一次操作,就是把乙個人從這一行中取出並放到行的最後,再從最後一列取出放到列的最後 那麼這兩種操作其實可以看做同乙個型別,都是把某乙個數取出並放到最後 那麼這個可以用splay來搞,用splay維護區間,...

洛谷P3960 列隊 splay

觀察到向左看齊和向前看齊真正影響的是當前行第y列和當前行的最後乙個人,於是每行除最後乙個建乙個splay,最後一列單獨建乙個splay。對於每次操作,刪除第x個splay樹的第y個,將最後一列的第x個 即第x行最後一列 加入第x個splay樹的末尾,再將刪除的那個節點加入最後一列的splay樹的末尾...