CSP2022 游记

我还是写一下吧……

Day -1

模拟赛。

成为机房垫底人。

Day 0

上午

补昨天模拟赛 T4。

下午

补昨天模拟赛 T4。

晚上

补昨天模拟赛 T4。

补完了后把昨天胡了没写的 APIO2014 连珠线写了。挺有意思的反悔贪心树形 dp 技巧。

然后回家了。

Day 1

上午

因为只去提高组,所以在家里 VP 了 CSP-S2021 的 T1-3。

为了适应考场没有代码补全、语法高亮之类的东西,赶紧把插件关了写。(flag)

T1,T3 半小时写完,T2 花了大概 1h 就写掉了。

11:00 起身去文渊,好坐校车去考点。

遇到了好多同学。/se

下午

12:30 校车出发。

大约 13:30 的样子抵达杭师大。

在里面面到了 djwj233。/se

devin 没来。/kel

14:00 左右进了机房。

那边的工作人员说话声好大啊。/yun

14:25 解压密码发下来,给的是 Belief2022,结果实际上是 belief2022???

我想,这实在是无法可想了。

开题。

先看 T1T2.

T1 大概先 bfs 一轮找到每个点距离那些点不超过 \(k\)?然后枚举似乎可以 meet in the middle?

T2 似乎随便分类讨论一下 rmq 就完了。

14:30 能开写了,先敲一个码头。以 T2 为例。(原来考场 VS Code 是有代码补全和语法高亮哒?

// with code highlight and code completion, I'd fly.
 
#include <algorithm>
#include <stdio.h>
#include <vector>
typedef unsigned uint;
typedef unsigned long long ullt;typedef long long llt;
typedef bool bol;typedef char chr;typedef void voi;
typedef double dbl;
template<typename T>bol _min(T&a,T b){return b<a?(a=b,true):false;}
template<typename T>bol _max(T&a,T b){return a<b?(a=b,true):false;}
int main(){
#ifdef MYEE
    freopen("QAQ.in","r",stdin);
    freopen("QAQ.out","w",stdout);
#else
    freopen("game.in","r",stdin);
    freopen("game.out","w",stdout);
#endif
    return 0;
}
 
// belief2022
 
/*
g++ game.cpp -o game -std=c++14 -lm -DMYEE -Wall
 
 
*/

厘清细节后就开始写,T1 花了 30min 就码完了。

做为优秀的稳健型选手,我维护了前 \(5\) 优解!会不会被卡常啊。

一遍过不了样例,怎么回事?原来距离是不超过 \(k+1\) 啊。

两遍过不了样例,怎么回事?原来我没有判 \(B,C\) 连通性啊。

然后直接过了大样例,稍微注意了一下 ullt 有没有开全,然后就码 T2 去了。

厘了一下细节,T2 花了 30min 就码完了,一遍过大样例,感觉不会写挂也就没有拍了。

在 线 乳 人。

struct max_ST{ // pogSTd
    std::vector<uint>Log2;
    std::vector<std::vector<llt> >S;
    voi build(llt*A,uint n){
        Log2.resize(n+1),Log2[0]=-1;
        for(uint i=1;i<=n;i++)Log2[i]=Log2[i>>1]+1;
        S.clear(),S.resize(Log2[n]+1,std::vector<llt>(n));
        for(uint i=0;i<n;i++)S[0][i]=A[i];
        for(uint i=1;i<=Log2[n];i++)for(uint j=0;j+(1u<<i)<=n;j++)
            S[i][j]=std::max(S[i-1][j],S[i-1][j+(1u<<(i-1))]);
    }
    llt find(uint l,uint r){uint s=Log2[r-l];return std::max(S[s][l],S[s][r-(1u<<s)]);}
};
struct min_ST{ // pogSTd
    std::vector<uint>Log2;
    std::vector<std::vector<llt> >S;
    voi build(llt*A,uint n){
        Log2.resize(n+1),Log2[0]=-1;
        for(uint i=1;i<=n;i++)Log2[i]=Log2[i>>1]+1;
        S.clear(),S.resize(Log2[n]+1,std::vector<llt>(n));
        for(uint i=0;i<n;i++)S[0][i]=A[i];
        for(uint i=1;i<=Log2[n];i++)for(uint j=0;j+(1u<<i)<=n;j++)
            S[i][j]=std::min(S[i-1][j],S[i-1][j+(1u<<(i-1))]);
    }
    llt find(uint l,uint r){uint s=Log2[r-l];return std::min(S[s][l],S[s][r-(1u<<s)]);}
};

看 T3,动 态 基 环 内 向 树。

什么鬼啊。/yun

看 T4。摆了。这么大码量有意思哦?

\(k=1\) 裸树上差分,\(k=2\) 直接全在链上选点 ddp,\(k=3\) 稍微讨论一下链外点的 ddp,随便讨论一下写个树上倍增就完了?

// feeling bad that being not able to type in Chinese.
// link-cut ji huan nei xiang shu ?
// do T4 first, plz.
// maybe easier than T3.

仔细想了想还是不要莽。

发现似乎直接让基环内向树森林的每个点出度均为 \(1\) 即可。

那不是直接写个 hash 就好了。/se/se/se

把出边相同的点整一起,搞一个线段树维护一下,区间 clear 区间 fill 全局求和。

// as they're all easy to do.
// while, let me think...
// the out deg of the whole points should all be 1.
// we can take the points whose out points same together, and do it with a Segment Tree, which is filled with hash.
// then it may be ok?
// by randomly making a map f: [1,n] -> [0,2^64), and sum the hash val, the possiblity of successiful check can be accepted.
// as the attack of birthday tell as that it's always ok, for n much smaller than 2^32.
 
//  -- yours, Myee Ye.

跑得很快啊!

此时 16:39,也就是 T3 花了 1h 就写完了。

考虑 T4 的细节。

// oh, i've had T3 done.
// now it's 16:39.
// can I finish it in 2 hours?
// just go for it!
 
// when watching back the whole contest, to think of it:
// is it a contest of Data Structure and Graph Theory?

然后 17:20 写完了 \(k=1,2\)

\(k=2\) 写了个 \(2\times2\) 的转移矩阵。直接 min-plus 矩阵乘法维护了。

// now it's 17:20, when I can pass the example 3 whose k=2.

\(k=3\) 写了个 \(5\times5\) 的转移矩阵。

\[\begin{bmatrix} v_f&v_f&v_f&v_f&v_f\\ v_o&v_o&v_o&+\infty&+\infty\\ 0&+\infty&+\infty&+\infty&+\infty\\ +\infty&0&+\infty&+\infty&+\infty\\ +\infty&+\infty&0&+\infty&+\infty\\ \end{bmatrix}\]

对应向量 \(\begin{pmatrix}f_1\\f_2\\f_3\\f_4\\f_5\end{pmatrix}\),其中 \(f_1\) 表示到当前根的最小权;\(f_2,f_3\) 表示到 \(1\) 的两个儿子的最小权,其中 \(2\) 在链上;\(f_4,f_5\)表示到 \(2\) 的两个儿子的最小权,其中 \(4\) 在链上。

合并左右两半时稍微讨论一下就好了。

会不会被卡常啊?

然后 18:02 码完了。

// now it's 18:02, when I can pass the example 4 whose k=3.

仔细检查一下,有没有什么问题?

\[21\times200000\times(2\times2+5\times5)\times8{\rm B}=974400000{\rm B}=929.26{\rm MB} \]

光转移矩阵的部分几乎就爆空间啦!(限制 \(1{\rm GB}\)

卡一卡矩阵大小。

卡成 \(4\times4\) 吧。\(4,5\) 可以合并。

\[\begin{bmatrix} v_f&v_f&v_f&v_f\\ v_o&v_o&v_o&+\infty\\ 0&+\infty&+\infty&+\infty\\ +\infty&0&0&+\infty\\ \end{bmatrix}\]

稳健的。

此时是 18:19。

// well, it get MLE.
// solve it at 18:19.

晚上

回到家了。

发现 T3 可以不用线段树维护,可以直接压边集栈维护。/cy

发现 T4 可以进一步压成 \(3\times3\) 的矩阵。/cy

发现 T4 可以点分,不用维护矩阵。/cy

Luogu 上 T1,T2,T4 开放民间数据评测,直接过了,感觉很稳。

infoj 上过了 T3,T4,T1T2 没测。

造 CSP-J2022 信友队数据评测 T4 的数据。

发现数据范围很小,\(n\le500,k\le100,v\le10^9\),感觉很憨。

随便写了个暴力,测了一下样例。

然后开始拿我的数据生成工具摁造数据。生成工具大概就长这样:

system("g++ gen.cpp -o gen -Wall -std=c++11");
FILE*fin=fopen("data_task.txt","r");
int l,r;
while(fscanf(fin,"%d%d",&l,&r)==2)
{
    fgets(C,100000,fin);
    // fprintf(stderr,"%s\n",C),fflush(stderr);
    char*c=C;
    while(*c&&*c!='\r'&&*c!='\n')c++;
    *c='\0';
    sprintf(D,"gen %s",C);
    while(l<=r)
    {
        sprintf(Sys,D,l);
        fprintf(stderr,"%s\n",Sys),fflush(stderr);
        system(Sys);
        l++;
    }
}
fclose(fin);

Generater 不敢乱发。好像写了一个长方形范围里的的随机点集生成器,然后删除重点。为了创人,我的 data_task.txt 写的很***钻。

Day 2

XJOI 上测了四题,全部过了。

Luogu T3 民间数据开放后测了也过了。

期望得分:\(100+100+100+100\)

posted @ 2022-10-31 10:16  myee  阅读(133)  评论(0编辑  收藏  举报