1. 程式人生 > >NOIP2017 Day2 T3 列隊(treap)

NOIP2017 Day2 T3 列隊(treap)

rand() closed lan struct for href long long img one

  可以直接用treap上大模擬...n+1個treap維護n行的前m-1個點和最後一列。

  需要支持刪除一個點或者一段區間,而空間並不支持存下所有的點的時候,可以用一個點代替一個區間,記錄區間首項的值和區間長度,這樣每次查詢某個點x的時候就可以用x在某個點y代表的區間裏的rank來得到x的值,然後把x刪去的時候,就把y這個區間從$[l,r]$拆分成$[l,x-1]$和$[x+1,r]$,重新加入。

  類似的題有NOI超級鋼琴

技術分享圖片
#include<iostream>
#include<cstring>
#include<cstdlib>
#include
<cstdio> #include<algorithm> #define ll long long #define int long long #define lt tree[x].ls #define rt tree[x].rs using namespace std; const int maxn=6000010; struct poi{ll beg; int rnd, size, ls, rs, len;}tree[maxn]; int n, m, Q, x, y, tott, tmp, rk; ll ans; int root[maxn], cnt[maxn], Len[maxn]; inline
void read(int &k) { int f=1; k=0; char c=getchar(); while(c<0 || c>9) c==- && (f=-1), c=getchar(); while(c<=9 && c>=0) k=k*10+c-0, c=getchar(); k*=f; } inline void build(int &x, ll beg, int len) { tree[x=++tott].beg=beg; tree[x].size=1
; tree[x].len=Len[x]=len; tree[x].rnd=rand()<<15|rand(); } inline void up(int x) { tree[x].size=tree[lt].size+tree[rt].size+1; tree[x].len=tree[lt].len+tree[rt].len+Len[x]; } void split(int x, int &l, int &r, int k) { if(!k) l=0, r=x; else if(tree[x].size==k) l=x, r=0; else if(tree[lt].size>=k) r=x, split(lt, l, lt, k), up(x); else l=x, split(rt, rt, r, k-tree[lt].size-1), up(x); } void rank(int x, int k) { if(tree[lt].len<k && tree[lt].len+Len[x]>=k) ans=k-tree[lt].len, rk+=tree[lt].size+1; else if(k<=tree[lt].len) rank(lt, k); else rk+=tree[lt].size+1, rank(rt, k-tree[lt].len-Len[x]); } void merge(int &x, int l, int r) { if(!l || !r) x=l+r; else if(tree[l].rnd<tree[r].rnd) x=l, merge(rt, rt, r), up(x); else x=r, merge(lt, l, lt), up(x); } inline void disc(int &Root, ll &poi, int pos) { int x, y; rk=0; rank(Root, pos); split(Root, Root, y, rk); if(rk-1) split(Root, Root, x, rk-1); else x=Root; if(ans-1) build(tmp, tree[x].beg, ans-1), merge(Root, Root, tmp); if(Len[x]-ans) build(tmp, tree[x].beg+ans*(Root==root[n+1]?m:1), Len[x]-ans), merge(Root, Root, tmp); merge(Root, Root, y); poi=x; } inline ll query(int posx, int posy) { if(posy!=m) { ll ANS, poi; disc(root[posx], poi, posy); ANS=tree[poi].beg+ans-1; build(tmp, ANS, 1); merge(root[n+1], root[n+1], tmp); disc(root[n+1], poi, posx); poi=tree[poi].beg+(ans-1)*m; build(tmp, poi, 1); merge(root[posx], root[posx], tmp); return ANS; } ll poi; disc(root[n+1], poi, posx); poi=tree[poi].beg+(ans-1)*m; build(tmp, poi, 1); merge(root[n+1], root[n+1], tmp); return poi; } #undef int int main() { srand(19260817); read(n); read(m); read(Q); for(int i=1;i<=n;i++) build(root[i], 1ll*1+(i-1)*m, m-1); build(root[n+1], m, n); for(int i=1;i<=Q;i++) read(x), read(y), printf("%lld\n", query(x, y)); }
View Code

NOIP2017 Day2 T3 列隊(treap)