首页 > 其他分享 >[SCOI2014] 方伯伯的OJ 解题报告

[SCOI2014] 方伯伯的OJ 解题报告

时间:2023-03-27 12:12:04浏览次数:50  
标签:rnk ch OJ int tot 解题 SCOI2014 fhq las

已经不记得平衡树的样子了。

Statement

给定一个 \(1\sim n\) 的序列,你有如下几个操作:

  • 改变一个人的编号
  • 将一个人放在序列开头
  • 将一个人放在序列结尾
  • 查询排名为 \(k\) 的编号

对于每次操作,输出操作前这个人的排名。

Analysis

可以把操作看作是以下几个步骤

  • 查找一个编号的排名
  • 删除一个编号
  • 在某一个位置加入一个编号
  • 查询某个排名的编号

这非常的平衡树,但是人数是 \(10^8\) 级别,而操作次数缺不多,因此我们尝试用编号的区间表示平衡树上的节点,用一个 map 存下一个区间对应的平衡树上的节点即可。

这就是本题大部分的转化,代码实现比较重要。

const int N = 5e5 + 5;
map<int, int> rnk;
struct Treap {
    int siz[N], ch[N][2], rnd[N], tot, L[N], R[N], fa[N], rt;
    il int NewNode(int l, int r) {
        siz[++tot] = r - l + 1;
        L[tot] = l, R[tot] = r;
        ch[tot][0] = ch[tot][1] = fa[tot] = 0; rnd[tot] = rand();
        rnk[l] = tot; return tot;
    }
    il void pushup(int p) {
        fa[ch[p][0]] = fa[ch[p][1]] = p;
        siz[p] = (R[p] - L[p] + 1) // 当前节点 siz
               + siz[ch[p][0]] + siz[ch[p][1]];
    }
    il int merge(int x, int y) {
        if (!x || !y) return x | y;
        if (rnd[x] < rnd[y]) {
            ch[x][1] = merge(ch[x][1], y);
            pushup(x); return x;
        }
        else {
            ch[y][0] = merge(x, ch[y][0]);
            pushup(y); return y;
        }
    }
    il void split(int p, int& x, int& y, int val) {
        if (!p) return x = y = 0, void();
        if (val <= siz[ch[p][0]]) {
            split(ch[p][0], x, y, val);
            ch[p][0] = y; y = fa[y] = p;
        }
        else {
            split(ch[p][1], x, y, val - siz[ch[p][0]] - R[p] + L[p] - 1);
            ch[p][1] = x; x = fa[x] = p;
        }
        pushup(p);
    }
    il int Rnk(int p) {
        int ret = siz[p] - siz[ch[p][1]];
        while (p != rt) {
            if (ch[fa[p]][1] == p) ret += siz[fa[p]] - siz[ch[fa[p]][1]];
            p = fa[p];
        }
        return ret;
    }
    il int kth(int p, int val) {
        if (val <= siz[ch[p][0]]) return kth(ch[p][0], val);
        val -= siz[ch[p][0]];
        if (val - R[p] + L[p] - 1 <= 0) return L[p] + val - 1;
        return kth(ch[p][1], val - R[p] + L[p] - 1);
    }
    il void ins(int p, int l, int r) {
        int x, y;
        split(rt, x, y, p - 1);
        rt = merge(merge(x, NewNode(l, r)), y);
    }
    il void del(int l, int r) {
        int x, y, z;
        split(rt, x, z, r);
        split(x, x, y, l - 1);
        rt = merge(x, z);
    }
}fhq;

int n, m, las;

int main() {
    srand(time(nullptr));
    read(n), read(m);
    rnk[1] = 1; fhq.ins(1, 1, n);
    for (int i = 1; i <= m; ++i) {
        int opt = read();
        if(opt == 1) {
            int x = read() - las, y = read() - las;
            int l = (--rnk.lower_bound(x + 1)) -> first, r = fhq.R[rnk[l]];
            write(las = fhq.Rnk(rnk[l]) - r + x);
            fhq.del(las - x + l, las - x + r);
            if (x > l) fhq.ins(las - x + l, l, x - 1);
            fhq.ins(las, y, y);
            if (r > x) fhq.ins(las + 1, x + 1, r);
        }
        else if (opt == 2) {
            int x = read() - las;
            int l = (--rnk.lower_bound(x + 1)) -> first, r = fhq.R[rnk[l]];
            write(las = fhq.Rnk(rnk[l]) - r + x);
            fhq.del(las - x + l, las - x + r);
            if (x > l) fhq.ins(las - x + l, l, x - 1);
            if (r > x) fhq.ins(las, x + 1, r);
            fhq.ins(1, x, x);
        }
        else if (opt == 3) {
            int x = read() - las;
            int l = (--rnk.lower_bound(x + 1)) -> first, r = fhq.R[rnk[l]];
            write(las = fhq.Rnk(rnk[l]) - r + x);
            fhq.del(las - x + l, las - x + r);
            if (x > l) fhq.ins(las - x + l, l, x - 1);
            if (r > x) fhq.ins(las, x + 1, r);
            fhq.ins(n, x, x);
        }
        else {
            int x = read() - las;
            write(las = fhq.kth(fhq.rt, x));
        }
    }
    return 0;
}

变量名字可能和实际用途不符。

标签:rnk,ch,OJ,int,tot,解题,SCOI2014,fhq,las
From: https://www.cnblogs.com/misterrabbit/p/17261111.html

相关文章

  • DUTOJ 1282: Zeratul与a+b=c bitset 小内存数组
    问题1282--Zeratul与a+b=c1282:Zeratul与a+b=c时间限制:1Sec  内存限制:32MB提交:148  解决:25[提交][状态][讨论版][命题人:Zeratul]题目描......
  • DUTOJ 1165: A Hard Game
    问题1165--AHardGame1165:AHardGame时间限制:1Sec  内存限制:128MB提交:26  解决:10[提交][状态][讨论版][命题人:201685076CJC]题目描......
  • bnuoj 12976 Collecting Gold 状压dp
    http://www.bnuoj.com/problem_show.php?pid=12976状态转移方程:dp[s|1<<j][j]=min(dp[s|1<<j][j],dp[s][i]+dis(i,j));code:#include<iostream>#include<stdio.h>#in......
  • 数据结构-->单链表OJ题--->讲解_03
    老铁们,现在开讲啦!!下面是本期的OJ试题:>1.给定一个带有头结点head的非空单链表,返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。现列图式样所示:>上图只有一......
  • POJ--3187 Backward Digit Sums(暴搜/减枝)
    记录5:302023-3-25http://poj.org/problem?id=3178reference:《挑战程序设计竞赛(第2版)》第二章练习题索引p135DescriptionFJandhiscowsenjoyplayingamenta......
  • bzoj 3669 魔法森林
    3669:[Noi2014]魔法森林TimeLimit: 30Sec  MemoryLimit: 512MBSubmit: 2690  Solved: 1667Submit][Status][Discuss]Description为了得到书法大家......
  • bzoj 2843 极地旅行社
    2843:极地旅行社TimeLimit: 10Sec  MemoryLimit: 256MBSubmit: 771  Solved: 473[Submit][Status][Discuss]Description不久之前,Mirko建立了一......
  • bzoj 2555 SubString
    2555:SubStringTimeLimit: 30Sec  MemoryLimit: 512MBSubmit: 2611  Solved: 784[Submit][Status][Discuss]Description      懒得写背景......
  • bzoj 2157 旅游
    2157:旅游TimeLimit:10Sec  MemoryLimit:259MBSubmit:1649  Solved:725[Submit][Status][Discuss]DescriptionRay乐忠于旅游,这次他来到了T城。......
  • bzoj 2631 tree
    2631:treeTimeLimit: 30Sec  MemoryLimit: 128MBSubmit: 4429  Solved: 1488[Submit][Status][Discuss]Description一棵n个点的树,每个点的初始......