洛谷P3960 列隊(Splay)

2022-02-27 23:01:21 字數 1433 閱讀 5385

傳送門

感覺自己好久不打資料結構已經完全不會了orz……

據說正解樹狀陣列?然而並不會

首先考慮一下每一次操作,就是把乙個人從這一行中取出並放到行的最後,再從最後一列取出放到列的最後

那麼這兩種操作其實可以看做同乙個型別,都是把某乙個數取出並放到最後

那麼這個可以用splay來搞,用splay維護區間,然後每一次找第k個相當於找第k大,然後刪除之後在末尾插入

然後如果直接開空間怕是要炸……那只能縮點,等做到這個點的時候再把它split出來……

然後……看**好了……

1

//minamoto

2 #include3 #include4

#define ll long long

5#define inf 0x3f3f3f3f

6using

namespace

std;

7#define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?eof:*p1++)

8char buf[1

<<21],*p1=buf,*p2=buf;

9 inline int

read()

19char sr[1

<<21],z[20];int c=-1

,z;20 inline void ot()

21 inline void

print(ll x)

26const

int n=1e7+5,maxn=3e5+5;27

intn,m,q,x,y;ll t,u;

28int fa[n],ch[n][2

],tot;ll l[n],r[n],sz[n];

29struct

splay

36 inline void upd(int

x)39

void rotate(int

x)44

void splay(int

x)50 upd(x),rt=x;51}

52 inline void

ins(ll v)

57 ll split(int

x,ll k)else

65 }else

69return

k;70

}71 ll rk(int

k)80}81

}82 inline void init(ll l,ll r)

83int build(int l,int r,int

f)91

}t[maxn];

92int

main()else

106}

107ot();

108return0;

109 }

洛谷P3960 列隊 splay

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

題解 P3960 列隊

考慮到每個點都是先橫向移動,然後再縱向移動,所以我們可以考慮每行維護乙個splay,最後一列再維護乙個splay。但是考慮到n和m的規模都是 3 10 5 級別的,普通的splay肯定會爆空間,所以我們使用動態開點的splay,對於每個節點記錄乙個l和乙個r,如果需要splay的元素在這個區間當中,...

題解 P3960 列隊

考慮到每個點都是先橫向移動,然後再縱向移動,所以我們可以考慮每行維護乙個splay,最後一列再維護乙個splay。但是考慮到n和m的規模都是 3 10 5 級別的,普通的splay肯定會爆空間,所以我們使用動態開點的splay,對於每個節點記錄乙個l和乙個r,如果需要splay的元素在這個區間當中,...