OI 退役日记 (fake)

浅谈being $A$part $F$rom $O$i

也算是一个很可以接受的旅途了

总结

OI

在SS的两年里大抵是学到了一点虚无的东西, 所有的便是远离文化课的寂静与…放松, 也算是挺可以接受的.

$size=1$的单调队列中, 最后终于还是剩下了一点音乐和番剧, 应该是为数不多的值得接受的内容了.

这大概就是高中的OI生涯了, 也算是可以接受.

新的题倒也做了一点, $160+251+18$, 所以用$AND$并列起来还是相当于一事无成吧, 乍一想也挺能接受的.

大概也能达到机房里其他人做题量的$1\%$, 可以接受.

值得愉悦的变化还有$Codeforces$的$Rating$从$\color{Blue}{Conless}$变成了$\color{Aqua}{Conless}$, 下降的少量$Rating$似乎意味着我的分数比起初三的$NOIP2018$并不会下降太多, 可喜可贺.

新的知识倒也确实学了一点, 爆零过的比赛数略多于新学的算法数, 也算是一个可观的数字.

学习

文化课的成绩单论班级上倒是有可观的进步, 从高一第一学期期中考的$Rank 46$进步到了高二第一学期期中考的$Rank 37$, 因此认为我被竞赛影响到文化课的言论也不可谓不愚蠢.

很多认识的聪慧的同学也会问到信息学对于数学、英语的帮助, 考虑到能力通常与排名正相关, 我的亲身经验可能也能在一定程度上让你走上信息学的康庄大道.

CSP-S 2020

考前准备

在考前的最后一个晚上为了放松心情选择玩完游戏就在$27:00 ,Oct.37^{th}$早早入睡, 也于次日$14:31$按时起床.

T0

调试好了电脑

写好了初始源文件

#include <bits/stdc++.h>
#include <con>

#define 最后一次 freopen
#define 比赛 (".in", "r", stdin);
#define 爆零 (".out", "w", stdout);
#define 终于还是要返回值得接受的失败结果吧 return -1;

using namespace std;

int left, right, y0, y1;

int main()
{
    最后一次比赛
    最后一次爆零
    left++; right++; y0++; y1++;
    终于还是要返回值得接受的失败结果吧
}

T1

是一道难度不大的背包类贪心, 每年一道贪心看来要在这里打卡呢.

根据数据$n\le 5000$不难想到$O(n^2)$做法

#include <bits/stdc++.h>

#define MAXN 0005

using namespace std;

int n, m, ans;
int d[MAXN], w[MAXN];

int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 0; i < n; i++)
        scanf("%d%d", &d[i], &w[i]);
    int mx = 1 << n;
    for (int i = 0; i < mx; i++)
    {
        int res = 0, sum = 0;
        for (int j = 0; j < n; j++)
            if ((mx >> j) & 1)
            {
                res += d[i];
                sum += w[i];
            }
        if (sum <= m)
            ans = max(ans, res);
    }
    printf("%d", ans);
    return 0;
}

T2

是一个稀疏图的单源最短路问题, 考虑到机房大佬说的图论问题数较大时考虑矩阵快速幂, 思考到矩阵快速幂优化Dij

typedef int matrix;

inline matrix pow(matrix a, maxtirx b) { return a + b; }

matrix dis[MAXN][MAXN];

void Dij()
{
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            for (int k = 1; k <= n; k++)
            {
                int res = pow(dis[i][j], dis[i][k]);
                if (res < dis[j][k])
                    dis[j][k] = dis[k][j] = res;
            }
}

T3

是一个树上问题, 观察到读入数据比较大, 考虑快读:

int main()
{
    ios::sync_with_stdio(true);
    for (int i = 1; i <= n; i++)
        cin >> a[i];
}

这几天学校做了不少树剖的题, 因此已经轻车熟路了, 虽然线段树并不是很记得怎么写区间修改, 我也还是手推了一个很好的写法:

#define sn segTree[node]

void change(int node, int l, int r, int val)
{
    if (!node)
        return;
    if (sn.l > r || sn.r < l)
        return;
    if (sn.l == sn.r)
    	sn.data += val;
    change(sn.lson, l, r, val);
    change(sn.rson, l, r, val);
    pushup();
}

T4

回归 【列队】, 我们先考虑在10h内将Splay的模板打上去.

#define root bTree[0].ch[1]
#define bn bTree[node]

class Splay
{

    int tot, cnt;

    struct TreeNode {
        int num, fa;
        int ch[2];
        int sum, recy;
    } bTree[MAXN];

    void update(int node)
    {
        bn.sum = bTree[bn.ch[0]].sum + bTree[bn.ch[1]].sum + bn.recy;
    }
    int identify(int node)
    {
        return bTree[bn.fa].ch[0] != node;
    }
    void connect(int node, int fa, int son)
    {
        bn.fa = fa;
        bTree[fa].ch[son] = node;
    }
    void rotate(int node)
    {
        int fa = bn.fa,
            gfa = bTree[fa].fa,
            son = identify(node),
            gson = identify(fa),
            nson = bn.ch[son ^ 1];
        connect(nson, fa, son);
        connect(fa, node, son ^ 1);
        connect(node, gfa, gson);
        update(fa);
        update(node);
    }
    void splay(int node, int to)
    {
        to = bTree[to].fa;
        while (bn.fa != to)
        {
            int nxt = bn.fa;
            if (bTree[nxt].fa == to)
                rotate(node);
            else {
                if (identify(nxt) == identify(node))
                {
                    rotate(nxt);
                    rotate(node);
                }
                else {
                    rotate(node);
                    rotate(node);
                }
            }
        }
    }
    int create(int num, int fa)
    {
        tot++;
        bTree[tot].num = num;
        bTree[tot].fa = fa;
        bTree[tot].sum = bTree[tot].recy = 1;
        return tot;
    }
    void destroy(int node)
    {
        bn.num = bn.ch[0] = bn.ch[1] = bn.sum = bn.fa = bn.recy = 0;
        if (node == tot)
            tot--;
    }

public:
    int getroot() { return root; }
    int find(int num)
    {
        int node = root;
        while (true)
        {
            if (bn.num == num)
            {
                splay(node, root);
                return node;
            }
            int nxt = (num >= bn.num);
            if (!bn.ch[nxt])
                return 0;
            node = bn.ch[nxt];
        }
    }
    int build(int num)
    {
        cnt++;
        if (root == 0)
        {
            create(num, 0);
            root = tot;
        }
        else {
            int node = root;
            while (true)
            {
                bn.sum++;
                if (num == bn.num)
                {
                    bn.recy++;
                    splay(node, root);
                    return node;
                }
                int nex = (num >= bn.num);
                if (!bn.ch[nex])
                {
                    create(num, node);
                    bn.ch[nex] = tot;
                    splay(tot, root);
                    return tot;
                }
                node = bn.ch[nex];
            }
        }
        return 0;
    }
    void push(int num)
    {
        int node = build(num);
        splay(node, root);
    }
    void pop(int num)
    {
        int pos = find(num);
        if (!pos)
            return;
        cnt--;
        if (bTree[pos].recy > 1)
        {
            bTree[pos].recy--;
            bTree[pos].sum--;
            return;
        }
        if (!bTree[pos].ch[0])
        {
            root = bTree[pos].ch[1];
            bTree[root].fa = 0;
        }
        else {
            int node = bTree[pos].ch[0];
            while (bn.ch[1])
                node = bn.ch[1];
            splay(node, bTree[pos].ch[0]);
            int rson = bTree[pos].ch[1];
            connect(rson, node, 1);
            connect(node, 0, 1);
            update(node);
        }
        destroy(pos);
    }
    int get_rank(int num)
    {
        int node = find(num);
        return bTree[bn.ch[0]].sum + 1;
    }
    int get_num(int k)
    {
        if (k > cnt)
            return -INF;
        int node = root;
        while (true)
        {
            int len = bn.sum - bTree[bn.ch[1]].sum;
            if (k > bTree[bn.ch[0]].sum && k <= len)
                break;
            if (k < len)
                node = bn.ch[0];
            else {
                k -= len;
                node = bn.ch[1];
            }
        }
        splay(node, root);
        return bn.num;
    }
    int upper(int num)
    {
        int node = root;
        int result = INF;
        while (node)
        {
            if (bn.num > num && bn.num < result)
                result = bn.num;
            if (num < bn.num)
                node = bn.ch[0];
            else node = bn.ch[1];
        }
        return result;
    }
    int lower(int num)
    {
        int node = root;
        int result = -INF;
        while (node)
        {
            if (bn.num < num && bn.num > result)
                result = bn.num;
            if (num > bn.num)
                node = bn.ch[1];
            else node = bn.ch[0];
        }
        return result;
    }
} btree;

可以看出这确实是一个短小精炼的数据结构, 我在考场上的时侯出了后面16个成员函数都很好地默了出来.

最终评测的结束也宣告了我5年OI生涯的终止, 最后可喜可贺的是, 对于定义一个考生能力的函数$F(i)=\frac{rank_i}{point_i}$来讲, 若不考虑无穷, 由于原函数值越小能力越强, 确实没有人的函数求值结果小于我.

未来

为了大学能获得ACM市赛爆零的机会, 需要积极投入文化课学习, 稳定在年级前列, 有望达到本科录取线.

听从机房大佬 的谆谆教诲要好好学好yìng语

希望文化课的成绩与另一位机房大佬 相比, 不要低超过900名

就这样吧, 下周再来填坑.

估计要被禁赛3年了8~