暑假清北学堂集训笔记

day -1

订票订得晚只好坐凌晨1点的火车……

day 0

7点钟到北京了,坐滴滴到酒店,然后去华北电力大学报道,路上看到一辆共享单车,弄了大半天才发现是坏的。。。

报完到就在旁边的餐厅吃了起来。

day 1

南小鸟(钟皓曦)讲 搜索 分治 倍增 贪心

ST表: f[i][j]表示 从i到i+2^j-1这2^j个位置的元素最大值 初始化: f[i][0]=z[i] 转移: f[i][j]=max(f[i][j-1],f[i+2^(j-1)][j-1])

LCA(最近公公祖先):f[i][j] 表示从树上编号为i的点向上走2^j步会走到哪个点 初始化: f[i][0]=father[i] 转移: f[i][j]=f[f[i][j-1][j-1]

求a,b,LCA时将a置为深度深的那个点,然后一直往上走,知道两个点深度相同,再将两个点同时向上走,走到同一个点时,那个点就是他们的LCA

inline void dfs(int now,int f) {
    for (unsigned i = 0;i < edges[now].size();i++)
		if (!deep[edges[now][i]] && edges[now][i] != f) {
	                deep[edges[now][i]] = deep[now]+1;
			father[edges[now][i]][0] = now;
			dfs(edges[now][i],now);
	        }
}
void init() {
    for (int j = 1;(1<<j) <= n;j++)
        for (int i = 1;i <= n;i++)
            if (father[i][j-1] != -1) father[i][j] = father[father[i][j-1]][j-1];
}
inline int lca(int a,int b) {
    if (deep[a] < deep[b]) swap(a,b);
    int i;
    for (i = 0;(1<<i) <= deep[a];i++);
    i--;
    for (int j = i;j >= 0;j--)
        if (deep[a]-(1<<j) >= deep[b]) a = father[a][j];
    if (a == b) return a;
    for (int j = i;j >= 0;j--) {
        if (father[a][j] != -1 && father[a][j] != father[b][j]) {
            a = father[a][j];
            b = father[b][j];
        }
    }
    return father[a][0];
}    

快速幂:快速幂是倍增和分治的结合,如:2^50可以分为(2^25)^2  2^25又可以分为(2^12)^2*2一直这样,我们就可以在O(log n)时间内求出x^n

inline int QuickPow(int x,int y) {
    if (y == 1) return x;
    int z = QuickPow(x,y>>1);
    if (y&1) return z*z*x%mod;
    return z*z%mod;
}

二分查找:二分查找可以在一个单调的序列中用O(log n)的时间找出一个数,它是一种分治

inline int find(int l,int r,int x) {
    if (r == l) return l;
    int mid = l+r>>1;
    if (x < a[mid]) return find(l,mid);
    return find(mid,r);
}

贪心:贪心一般形式是,以某种方式将所有物品排序,排序后按照从小到大进行选择

搜索:dfs,bfs

搜索优化:

剪枝:把不优于当前最优解的状态剪掉

卡时:卡时是一种骗分技巧,一般用于最优性问题,当程序准备超时时,直接输出当前答案,然后结束程序

#include <cstdlib>
#include <cstdio>
#include <ctime>
int t,ans;
inline void dfs(...) {
    if (clock-t >= 990) {
        printf("%d",ans);
        exit(0);
    }
    ...
}
int main() {
    t = clock();
    ...
    dfs(...);
    printf("%d",ans);
    return 0;
}

晚上测试

第一题是一题不可做的模拟题!!!

我写里1.5h+

结果还是没能调出来

第二题写了一个四重循环加卡时

第三题没看

结果

……

0+0+0=0

爆零啦!!!!!!!!!!!!!  有大佬200 Orz %%%

day 2

一上午都在讲数论,作为五年级小学生表示听不懂!!!!!!!!!!!!!!!!!!!

中午南小鸟走了,杨乐来了

杨乐讲了一些背包和记忆化搜索

day 3

上午,杨乐又讲了一些线性dp

LIS:最长不下降子序列

假设我们需要求以x结尾的最长下降子序列dp[x],由最忧性可得,我们除去最后一个位置(也就是x),还是一段最长下降,

那我们可以枚举这个子序列的结尾y,最优值就是dp[y]。但需要注意的是,必须保证A[x] < A[Y], x比 Y要低,才满足下降的要求。

我们从所有枚举的结果中找到一个最大的即可。

转移方程:dp[i] = max{dp[j]+1} (j<i     a[i]<a[j])

LCS:最长公共子序列

假设我们需要求两个序列分别以i,j结尾的最长公共子序列

dp[i][j], 接下来我们可以分几种情况讨论:

a[i]不在公共子序列中,那么长度则等于dp[i-1][j]

b[j]不在公共子序列中,那么长度则等于dp[i][j-1]

a[i]与b[j]都在子序列中,并且两者匹配,那么长度等于dp[i-1][j-1]+1

然后还讲了区间dp,二维平面dp,状态划分dp

下午杨乐又讲了序列划分dp,树形dp,状态压缩dp……

day 4

杨乐也走了,黄致焕来了

黄致焕讲了栈,单调栈,队列,单调队列

day4就这样愉快的结束了

day 5

黄致焕又讲了并查集,堆,可并堆,树状数组,左偏树等离奇数据结构。。。

并查集:

并查集是一种树形数据结构支持合并,查找祖先

查找如下:

inline int find(int x) {  //father[x]表示x的祖先,father[x]=x表示x是根节点
    if (father[x] == x) return x;  //找到根节点
    return father[x] = find(father[x]);  //祖先的祖先就是我的祖先
}

合并如下:

inline void Union(int x,int y) { father[find(x)] = find(y); }  //合并祖先

堆:

定义:一棵满足以下两个性质的二叉树:

1.父节点权值大于等于(大根堆)或小于等于(小根堆)任何一个儿子的权值。

2.每个节点的左子树和右子树都是一个堆。

左偏树:

左偏树是可并堆的一种

在左偏树中,每个节点包含两个属性:权值和距离(dist)。除了之前二叉堆支持的操作以外,左偏树还支持合并(merge)操作。

左偏树的每个节点都满足做儿子的dist大于右儿子的dist,每个节点的dist的值即为该子树中与该节点最近的点的距离。

合并如下:

inline int merge(int x,int y) {
    if (!x || !y) return x|y;  //判断空树
    if (heap[x].key < heap[y].key) swap(x,y);  //让键值大的为x
    heap[x].rson = merge(y,heap[x].rson);  //将右儿子与y合并
    if (heap[heap[x].lson].dist < heap[heap[x].rson].dist) swap(heap[x].lson,heap[x].rson);  //让dist大的为左儿子
    heap[x].dist = heap[heap[x].rson].dist+1;  //算dist
    return x;
}

删除如下:

inline int del(int x) { return merge(heap[x].lson,heap[x].rson); }  //将左右儿子合并

然后老师又讲了很迷很迷的一些数据结构……

day 6

姜志豪来了,图论也来啦

树的遍历

BFS:一开始队列中有一个点,将一个点出队,将它的子结点全都入队。

DFS:递归到一个点时,依次递归它的子结点。

最小生成树

prim:

先随机找一个点x作为根,然后维护一个集合S(存已经连通的点)和一个集合D(存当前连接S中所有点的线段,两端点都在S中的除外)

初始化S={x},D={x所连接的所有边};

每次在D中选一个权值最小的边,然后将该边删去。该边所连接的另一个点放入S中,直到S中点数=全部点数。

这里记顶点数n,边数m,

时间复杂度:O(m log n)

kruskal:

将边权从小到大排序,每次选择边权最小的,如果当前边连接的点已经连通了,就不选这条边。

利用并查集维护是否连通。

m为图中的边数

时间复杂度:O(m log m)

最短路算法

floyd:

设dist[i][j]为i~j的距离,则有动态转移方程:dist[i][j] = max{dist[i][k]+dist[k][j]}

dijkstra:

a.初始时,S只包含源点,即S={v},v的距离为0。U包含除v外的其他顶点,即:U={其余顶点},若v与U中顶点u有边,则正常有权值,若u不是v的出边邻接点,则权值为∞。

b.从U中选取一个距离v最小的顶点k,把k,加入S中(该选定的距离就是v到k的最短路径长度)。

c.以k为新考虑的中间点,修改U中各顶点的距离;若从源点v到顶点u的距离(经过顶点k)比原来距离(不经过顶点k)短,则修改顶点u的距离值,修改后的距离值的顶点k的距离加上边上的权。

d.重复步骤b和c直到所有顶点都包含在S中。

spfa:

首先建立一个数组s,s[i]代表从始点到i点所需要的最短距离。

利用一个队列进行松弛操作:

初始化s[i]=∞;

首先将始点入队,然后将始点所连接的点x入队。入队的时候,将始点到x的距离d赋值给s[i]。对于始点所连接的所有点都进行如下操作,弹出队首元素。

访问队首元素y,将队首元素y所连接的所有的点都入队。假如其中一个点为z,则判定一下s[z]是否大于s[y]+< y,z >边权。如果大于,则松弛一下,把s[y]赋值为较小的那个。

toposort:

入度:有多少条边指向他

出度:有多少条边从他发出

先统计每个点的入度,假如a->b,则in[b]++;

用栈来维护入度=0的点。

若栈非空,则在栈中弹出一个元素(并输出),然后枚举这个点能到的每一个点将它的入度-1.如果入度=0,则压入栈中。

如果没有输出所有的顶点,则有向图中一定存在环

强连通分量:

……

晚上,第二波考试

第一题:水题,n^2大暴力

第二题:不会做,仍然n^2大暴力

第三题:想到正解,写炸了!!!

100+20+30=150  有大佬270 Orz %%%

day 7

Trie树,KMP,AC自动机……

day 111

离noip还有1周……

时间: 2024-12-11 00:16:03

暑假清北学堂集训笔记的相关文章

2017清北学堂集训笔记——图论

我们进入一个新的模块——图论! emmmmm这个专题更出来可能有点慢别介意,原因是要划的图和要给代码加的注释比较多,更重要的就是...这几个晚上我在追剧!!我们的少年时代超级超级超级好看,剧情很燃啊!!咳咳,好吧下面回归正题. 一.图的存储: 1.邻接矩阵: 假设有n个节点,建立一个n×n的矩阵,第i号节点能到达第j号节点就将[i][j]标记为1(有权值标记为权值), 样例如下图: 1 /*无向图,无权值*/ 2 int a[MAXN][MAXN];//邻接矩阵 3 int x,y;//两座城市

2017清北学堂集训笔记——动态规划Part2

啊~到下午啦,我们进入Part2!--一个简洁的开头 我们来探讨第一类问题--路径行走问题 经典例题:方格取数(Luogu 1004) 设有 N*N 的方格图 (N<=9),我们将其中的某些方格中填入正整数,而其他的方格中则放入数字 0.* 某人从图的左上角的 A 点出发,可以向下行走,也可以向右走,直到到达右下角的 B 点.在走过的路上,他可以取走方格中的数(取走后的方格中将变为数字 0).* 此人从 A 点到 B 点共走两次,试找出 2 条这样的路径,使得取得的数之和为最大.- 与数字金字塔

清北学堂2017NOIP冬令营入学测试 P4744 A’s problem(a)

清北学堂2017NOIP冬令营入学测试 P4744 A's problem(a) 时间: 1000ms / 空间: 655360KiB / Java类名: Main 背景 冬令营入学测试题,每三天结算一次成绩.参与享优惠 描述 这是一道有背景的题目,小A也是一个有故事的人.但可惜的是这里纸张太小,小A无法把故事详细地说给大家听.可能小A自己也讲不清楚自己的故事,因为如果讲清了,也就没有这道题目了-- 小A的问题是这个样子,它找到了n份不同的工作,第i份工作每个月有ai的工资,每份工作需要小A每天

铁轨 清北学堂 线段树

铁轨 清北学堂 线段树 [题目描述] R 国的铁轨经常会进行重新修建. R 国是一个细长的国家,一共有 n 个城市排成一排,首都位于 1 号城市,相邻两个城市之间有铁路相连. 每次新建铁轨的时候,一定是从首都开始修建,直到某一个城市为止,这其间的铁路都会变成新版本的设 施,而旧设施会被拆除.然而,由于 R 国的工程师脑子不太好使,任意两种不同版本的铁路之间都无法连 接,因此必须要进行换乘. 现在给出你修建铁轨的操作,小 R 时不时第会想问你,如果在第 x 个城市到第 y 个城市之间随机选择一个

清北学堂 最大速度

最大速度 (maxv.pas/c/cpp) [问题描述] Ron的老爸的Flying Car出了些问题,现在必须要在地上跑到很大的速度才能飞起来,但是Flying Car飞起来的那一刻不能被麻瓜看到.为了确保安全飞起来,需要知道车到可以飞起来的地方时所能达到的最大速度.他的Flying Car一开始拥有一个初速度,移动一次增加速度1:因为车道很窄,宽度只有1,所以仅当要转向的方向有路时才能转,左转一次减少速度35,右转一次减少速度40,当前进.左转.右转都无路可走的时候,调头(连左转两次或连右转

清北学堂2017NOIP冬令营入学测试

P4744 A's problem(a) 时间: 1000ms / 空间: 655360KiB / Java类名: Main 背景 冬令营入学测试题,每三天结算一次成绩.参与享优惠 描述 这是一道有背景的题目,小A也是一个有故事的人.但可惜的是这里纸张太小,小A无法把故事详细地说给大家听.可能小A自己也讲不清楚自己的故事,因为如果讲清了,也就没有这道题目了-- 小A的问题是这个样子,它找到了n份不同的工作,第i份工作每个月有ai的工资,每份工作需要小A每天工作8小时,一周工作7天.小A想知道性价

清北学堂 逃亡的准备

  逃亡的准备 (hallows.pas/c/cpp)   [问题描述] 在<Harry Potter and the Deathly Hallows>中,Harry Potter他们一起逃亡,现在有许多的东西要放到赫敏的包里面,但是包的大小有限,所以我们只能够在里面放入非常重要的物品,现在给出该种物品的数量.体积.价值的数值,希望你能够算出怎样能使背包的价值最大的组合方式,并且输出这个数值,赫敏会非常地感谢你. [输入文件](hallows.in) (1)第一行有2个整数,物品种数n和背包装

清北学堂 站军姿

/*2bc*cosA=b^2+c^2-a^2 模拟计算 50分*/ #include<iostream> #include<cstdio> #include<cmath> using namespace std; const double t=3.1415926535898; int n; double a,b,c,x,y,z,x2,y2,z2,s,k,m,w,p; int main () { freopen ("standing.in","

5月3日济南清北学堂随堂测试题目

消失的数字(number) Time Limit:1000ms   Memory Limit:128MB 题目描述 rsy拥有n个数,这n个数分别是a1,a2,-,an. 后来出现了一个熊孩子zhw,用橡皮擦去了其中若干个数字,并且打乱了剩下的数字.rsy赶到现场后只剩下了m个数字b1,b2,-,bm,她想知道哪些数字被擦去了. 现在你需要告诉rsy被擦去的n-m个数是什么. 输入格式(number.in) 第一行一个数n,第二行n个数ai,表示一开始的数字. 第三行一个数m,第四行m个数bi,