NOIP2017 列隊
阿新 • • 發佈:2018-04-01
vector n-1 reg 前言 esp ++ code pla 暴力 ,把連續的整塊看做一個點。
每次先二分找到對應的整塊,然後把整塊分開再重新插入\(Splay\),一直做下去即可。
超級暴力的\(Splay\)直接硬上......
我發現自己寫不出來,瑟瑟發抖......(後來發現ZSY和YYB寫的就是這個,太強了ORZ!)
所以比較好寫的做法是:
如果是初始元素那麽直接輸出就行了。
如果不是呢?
我們開\(vector\)記錄每一行和最後一列中後來加入的元素。
如果不是直接到\(vector\)中取即可。
這題就做完了,線段木寫起來真的非常的舒服(QwQ)。
NOIP2017 列隊
題目大意
有一個\(n*m\)的列隊方格。
一開始,這個列隊中\((i,j)\)的人的編號為\((i-1)m+j\)。
每次下達一個指令\((x,y)\),使得\((x,y)\)這個位置的人出列。
然後:
- 向左看齊,所有人向左填補空位。
- 向前看齊,所有人向前填補空位。
不難發現兩次看齊後空位變到了\((n,m)\),然後令剛才出列的人回到這個位置。
對於依次進行的\(Q\)次指令,你需要輸出出列的人的編號。
數據範圍:\(n,m,Q \leq 3*10^5\)
前言
NOIP此題50分選手現在依舊覺得:好神啊這題(QwQ)。
我自己的想法是:
對於每一行和最後一列維護一個\(Splay\)
每次先二分找到對應的整塊,然後把整塊分開再重新插入\(Splay\),一直做下去即可。
超級暴力的\(Splay\)直接硬上......
我發現自己寫不出來,瑟瑟發抖......(後來發現ZSY和YYB寫的就是這個,太強了ORZ!)
所以比較好寫的做法是:
題解
依舊順著上面說的那種做法,
修改\((x,y)\)影響的只有第\(x\)行和第\(m\)列。
那麽我們開\(n\)棵 線段木(動態開點) 來維護每行的前\(m-1\)列,再開一棵維護最後一列。
可以發現初始每一棵線段木中存的元素是連續的一段。
所以我們用線段木維護初始每一行的元素,每次二分查找看答案是不是初始元素。
如果不是呢?
我們開\(vector\)記錄每一行和最後一列中後來加入的元素。
如果不是直接到\(vector\)中取即可。
這題就做完了,線段木寫起來真的非常的舒服(QwQ)。
實現代碼
#include<bits/stdc++.h> #define RG register #define IL inline #define _ 300005 using namespace std; IL int gi(){ RG int data = 0 , m = 1; RG char ch = 0; while(ch != '-' && (ch<'0' || ch > '9')) ch = getchar(); if(ch == '-'){m = 0; ch = getchar();} while(ch>='0' && ch<='9'){data = (data<<1) + (data<<3) + ch - '0' ; ch = getchar();} return (m) ? data : -data ; } struct Segment_Tree{int ls,rs,sz;}t[60*_]; int n,m,f[_],rt[_],tot,Lg,Q; vector<long long>vec[_] ; int Query(RG int o,RG int l,RG int r,RG int K){ if(l == r) return l ; RG int mid = (l + r) >> 1 , SZ = (mid-l+1) - t[t[o].ls].sz ; if(K <= SZ) return Query(t[o].ls , l , mid , K) ; else if(K > SZ) return Query(t[o].rs , mid + 1 , r , K - SZ) ; } void Delete(RG int &o,RG int l,RG int r,RG int p){ if(!o)o = ++tot ; ++ t[o].sz; if(l == r)return ; RG int mid = (l + r) >> 1; if(p <= mid) Delete(t[o].ls , l , mid , p) ; else if(p > mid) Delete(t[o].rs , mid + 1 , r , p) ; } IL long long Delete_line(RG int x,RG int kth){ RG int id = Query(rt[x] , 1 , Lg , kth) ; Delete(rt[x] , 1 , Lg , id) ; return (id <= m-1) ? 1ll * (x-1) * m + id : vec[x][id-m]; } IL long long Delete_row(RG int kth){ RG int id = Query(rt[n+1] , 1 , Lg , kth) ; Delete(rt[n+1] , 1 , Lg , id) ; return (id <= n) ? 1ll * id * m : vec[n+1][id-n-1]; } int main(){ n = gi(); m = gi(); Q = gi(); Lg = max(n , m) + Q + 1; long long id , id2 ; while(Q --){ RG int x = gi() , y = gi() ; if(y ^ m){ id = Delete_line(x , y) ; id2 = Delete_row(x) ; vec[x].push_back(id2) ; vec[n+1].push_back(id) ; } else{ id = Delete_row(x) ; vec[n+1].push_back(id) ; } printf("%lld\n" , id) ; }return 0; }
NOIP2017 列隊