2021.10.25-10.31_training
CCPC#2020威海
G.Caesar Cipher
很经典的hash+线段树,以后遇到“求解序列是否相同”都可以试试hash
这里的数字要对65536取模,可以存储每个区间的mn和mx值,这样就可以知道是否有数字达到了65536,然后,对于任何满足内部所有数字都达到了65536的区间清零。
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128#include<bits/stdc++.h>using namespace std;typedef long long ll;type ...
2021.10.30随笔
一
现在是周六晚9点27分。现在我正一个人坐在校队机房里,虽然窗户外面就是著名的兴庆宫,但是在这寂静的夜里,也只有断断续续的车流声与我作伴…我想,这真是个写点东西,发发牢骚的好时机啊
于是打开博客,我又翻了翻一年前自己写的东西,感觉是真的中二(~ ̄▽ ̄)~不过了一下回顾当初立下的flag,也算是勉强达成了?如果不算cf的还没上橙的话
二
感觉人真的很神奇,随着时间的推进,不经意间就会领会到很多奇奇怪怪的东西。在大三的这个时候,在这样一个不算太舒服的处境下,我反而活得不那么拧巴了。这两个月里,每天的生活似乎都离不开共享单车了。下课后,要从主楼的教室骑到位于学校西北角的机房;晚上十点半,再从机房骑到学校东南角的宿舍。最有意思的是,因为每天晚上都是最后一个从西一楼二楼出来的人,那个负责关门的阿姨都认识我了🤣
五月开始到现在,头晕仍然没有好,每天写代码都是昏沉沉的,但是心情其实并没有太受影响。晚上收拾好电脑回宿舍,在梧桐西道骑行的时候,路灯撒下淡淡的黄晕,耳机里放着Carmen Suite No. 2:III. Nocturne,给了我有一种很不真实的祥和与平静。也许在若干年以后,我仍会 ...
Kosaraju Algorithm
小记
同样作为强连通分量相关的算法,tarjan算法似乎要出名得多,实际上我也是两天前才知道还有个叫Kosaraju的算法。后者与前者的理论复杂度其实是一样的,而且实际情况应用中前者甚至会稍快一些。但是Kosaraju算法有着tarjan所没有的优势——Kosaraju可以与bitset相结合,从而能够在极为优秀的复杂度内解决一些稠密图内的问题。
算法流程
首先对图进行第一遍dfs,并把遍历到的点压入栈中。值得注意的是,这里的压栈要写在dfs函数的最后,即在一个节点及其后继完全访问完毕后再压栈操作。
对这个图求反,即把所有边反向。然后在这个反图上跑dfs。注意这里跑dfs时,选取上一步中栈顶的元素作为起点。一次dfs中遇到的所有点,都属于同一个强连通分量,并且标记他们,注意在dfs过程中,不能访问已经标记过的点。如果dfs结束,那么再次从栈顶取一个未被标记的元素,以它为起点继续在反图上跑dfs,如此往复,直到栈为空。
算法结束,所有的强连通分量已求出。
123456789101112131415161718192021222324252627282930313233343536 ...
2021_10.13-10.19_training
ICPC#2020澳门站
C.Club Assignment
挺小清新的一个构造题。要尽量使得高位能有1,如果无法避免有的异或值高位为0的话,那么就继续递归地往下讨论,并且这一位不同的数字之间的相对位置关系对答案就不会产生影响了。
模拟赛的过程中没写完,下来花了1个多小时一遍AC了,还是挺爽的。
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134#include<bits/stdc++.h>using namespace std;typede ...
二分图
二分图最大匹配
图的匹配,即由一组没有公共端点的不是圈的边构成的集合,我们这里需要使得这个集合尽可能大,即寻找二分图的最大匹配
这里需要先了解两个定义:
交错路:给定图G的一个匹配M,如果一条路径的边交替出现在M中和不出现在M中,我们称之为一条M-交错路径
增广路(增广轨):如果一条M-交错路径,它的两个端点都不与M中的边关联,我们称这条路径叫做M-增广路径
匈牙利算法
该算法本质上就是不停地找增广路并更新答案,复杂度为O(nm)O(nm)O(nm)。
算法的正确性证明可以看这里
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960struct augment_path { vector<vector<int> > g; vector<int> pa; // 匹配 vector<int> pb; vector<int> vis; ...
2-SAT
算法简介
给出若干个元素,其中每个元素非真即假。然后再给出若干个包含这些元素的命题,要求找出这些元素的可能取值,使得所有给出的命题成立。
问题的初始模型网上都已经讲的很清楚了,具体可以参考传送门。这里我只会放一些本人在的学习过程中踩过的坑
Tarjan 缩点
一般来说,2-SAT 的模型所建出来的图都是对称的。这里的对称该如何理解呢?
给出两个元素A,B。那么如果A,B不能共存,那么A->B’,B->A’。即如果选了A,那么只能选B’;如果选了B,那么只能选A’。所以如果能由X推出Y,那么就能从Y’推出X’,这就是所谓的"对称"。
先使用 tarjan 算法跑一边强连通分量,如果存在一个元素X能推出元素X’,那么说明X’也能推出X,所以一定会导致矛盾产生,那么问题一定无解。
如果问题有解,那么我们就反向拓扑排序,依次选择排序过程中遇到的点。由于求强连通分量的时候利用了栈,这就是一个天然的反向拓扑排序的结构,所以选择最先进栈的强连通分量就行了。
至于为什么需要反向拓扑排序,其实博主也不能严格证明出它的正确性,这个需要自己感性理解。首先可以先自己推算一下 ...
2021_9.29-10.5训练
ICPC网络赛#2021第二场
题解传送门
H.Set
对于这种咋一看不知从何入手的题目,可以想想能否“乱搞”,即利用某种极端的条件或者这个题目某种特殊的性质入手研究整个问题。
这里需要知道一个东西,叫做Union bound,然后我们可以计算出随机选一组解为非法解的概率的上界,结果惊人地小,于是我们可以直接使用random_shuffle构造一组答案,问题就解决了
123456789101112131415161718192021222324252627282930#include<bits/stdc++.h>using namespace std;typedef long long ll;typedef pair<int,int>pii;typedef double db;const int maxn=1e5+5;const ll mod=998244353;const double eps=1e-10;int r,k;vector<int>vec[300];int main(){ int T=1;//scanf("%d& ...
2021_9.22-9.28训练
ICPC2020上海站
题解传送门
E.The Journey of Geor Autumn
这道题看似复杂,其实就是个很直观的递推。乍一看貌似无从下手,但是可以从最小数的放置方式入手,从而实现递推求解。注意这里递推的方式,可以手算一下,还是很好化简的。
12345678910111213141516171819202122232425262728293031323334353637#include<bits/stdc++.h>using namespace std;typedef long long ll;typedef pair<int,int>pii;typedef double db;const int maxn=1e7+5;const ll mod=998244353;const double eps=1e-10;int n,k;ll f[maxn];ll fac[maxn],infac[maxn];ll quick_p(ll x,ll y){ ll res=1; while(y){ if(y&1)res*=x,res ...
2021_9.8-9.14训练
ICPC2020南京站
C.Certain Scientific Railgun
这道题算是个挺巧妙的构造题吧,可以对原图进行若干次对称变换,这样就可以固定住决策,从而极大地简化了代码量 然而简化之后还是很折磨
决策分为两种情况,首先只向左走,然后再上下;或者向左走后再向右,然后上下走。
按照题解的做法维护四个set就行了接下来这道题需要的就只是亿点点细节
注意一下,有可能最优解只是上下走,要注意特判,或者交换一下X,Y轴再算一次。我这里的做法是增加了一个坐标为(0,0)(0,0)(0,0)的点,这样能保证在X轴上能“移动一次”(即使这时候的花费为0),从而包含了只上下走的情况。
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 ...
2021_9月1日-9月7日训练
9.02
训练赛传送门
Problem I. Minimum Diameter Spanning Tree
这道题需要一定的前置知识,比如这篇博客
当明白图的绝对中心这个概念后,这道题就迎刃而解了。
注意理解上述博客中的折线最低点的求解过程。因为都是斜率为1的折线,所以可以通过简单的推导得到最低点与折线的关系式,进而求解。然后最后找点则根据中心点的位置bfs即可,注意中心点可能在某条线段的端点上,所以这种情况下要特判。
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104#include<bits/stdc++.h>using namespace std;typedef long long ll;typedef pair ...