NOIP2017 列队
NOIP2017 列队
这题看上去 fhq_Treap 一脸可做
看完 ** 的数据范围就不可做了
毕竟 d2t3 ,得有点骚操作的
我们发现操作次数并不多
可以试着“动态开点”
就是用到这个位置的时候再给它开辟一个节点
不用就和其他不用的连为一体作为一个节点就好了
挺麻烦不过代码并不长
核心部分代码:
pair<int, int> Split(int cur, ll k) { if(!cur || !k) return make_pair(0, cur); pair<int, int> res; if(t[lson].siz >= k) { res = Split(lson, k); lson = res.second; pushup(cur); res.second = cur; } else if(t[lson].siz + t[cur].len() >= k) { register ll l = t[cur].l, r = t[cur].r; int newrt; k -= t[lson].siz; t[cur].rerange(l, l + k - 1ll); newrt = newnode(l + k, r); res.second = Merge(newrt, rson); rson = 0; if(t[cur].len() <= 0) cur = lson; pushup(cur); res.first = cur; } else { res = Split(rson, k - t[lson].siz - t[cur].len()); rson = res.first; pushup(cur); res.first = cur; } return res; }
意思就是说, 如果当前的区间是我想要操作的区间(要 Split 的区间),我就给它多开另一个节点,让他们两个作为裂开后的左右两部分
根据 fhq_Treap 的经典 Split 操作的过程,我们不难写出上面代码的细节
需要额外注意的就是在 newnode 的时候需要把节点的 size 搞一下
完整代码:
#include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cctype> #include<cstdio> #include<ctime> #define lson t[cur].ch[0] #define rson t[cur].ch[1] using namespace std; typedef long long ll; const int MAXN = 300005; struct Node{ ll siz, l, r; int ch[2], prio; Node() {ch[0] = ch[1] = 0; siz = l = r = 0ll;} inline void clear() { ch[0] = ch[1] = prio = 0; siz = l = r = 0ll; return; } inline void rerange(ll x, ll y) { l = x; r = y; return; } inline ll len() { return r - l + 1ll; } }t[MAXN * 16]; int n, m, q, poolcur; ll Root[MAXN]; inline int newnode(ll l, ll r) { if(l > r) return 0; register int cur = ++poolcur; t[cur].clear(); t[cur].l = l; t[cur].r = r; t[cur].siz = t[cur].len(); t[cur].prio = rand(); return cur; } inline void pushup(int cur) { t[cur].siz = t[lson].siz + t[rson].siz + t[cur].len(); return; } int Merge(int x, int y) { if(!x) return y; if(!y) return x; if(t[x].prio < t[y].prio) { t[x].ch[1] = Merge(t[x].ch[1], y); pushup(x); return x; } else { t[y].ch[0] = Merge(x, t[y].ch[0]); pushup(y); return y; } } pair<int, int> Split(int cur, ll k) { if(!cur || !k) return make_pair(0, cur); pair<int, int> res; if(t[lson].siz >= k) { res = Split(lson, k); lson = res.second; pushup(cur); res.second = cur; } else if(t[lson].siz + t[cur].len() >= k) { register ll l = t[cur].l, r = t[cur].r; int newrt; k -= t[lson].siz; t[cur].rerange(l, l + k - 1ll); newrt = newnode(l + k, r); res.second = Merge(newrt, rson); rson = 0; if(t[cur].len() <= 0) cur = lson; pushup(cur); res.first = cur; } else { res = Split(rson, k - t[lson].siz - t[cur].len()); rson = res.first; pushup(cur); res.first = cur; } return res; } inline void build() { for(int i = 1; i <= n; ++i) Root[i] = newnode(((ll)i - 1ll) * (ll)m + 1ll, (ll)i * (ll)m - 1ll); Root[0] = newnode((ll)m, (ll)m); int cur; for(int i = 2; i <= n; ++i) { cur = newnode((ll)i * (ll)m, (ll)i * (ll)m); Root[0] = Merge(Root[0], cur); } return; } inline void work(ll x, ll y) { pair<int, int> pre1, per1, pre2, per2; if(y != m) { pre1 = Split(Root[0], x); per1 = Split(pre1.first, x - 1ll); pre2 = Split(Root[x], y); per2 = Split(pre2.first, y - 1ll); printf("%lld\n", t[per2.second].l); Root[0] = Merge(Merge(per1.first, pre1.second), per2.second); Root[x] = Merge(Merge(per2.first, pre2.second), per1.second); } else { pre1 = Split(Root[0], x); per1 = Split(pre1.first, x - 1ll); printf("%lld\n", t[per1.second].l); Root[0] = Merge(Merge(per1.first, pre1.second), per1.second); } return; } int main() { // freopen("dui.in", "r", stdin); // freopen("dui.out", "w", stdout); srand(time(NULL)); scanf("%d%d%d", &n, &m, &q); build(); ll x, y; while(q--) { scanf("%lld%lld", &x, &y); work(x, y); } // fclose(stdin); // fclose(stdout); return 0; }
禁止诸如开发者知识库/布布扣/码迷/学步园/马开东等 copy 他人博文乃至博客的网站转载
,用户转载请注明出处:https://www.cnblogs.com/xcysblog/