我是靠谱客的博主 爱听歌铃铛,这篇文章主要介绍大一ACM暑假集训第二周学习总结,现在分享给大家,希望可以做个参考。

Week_2

Day_1

求最大公约数时使用GCD

int gcd(int a,int b)
{
if(b==0)return a;
return gcd(b,a%b);
}

当遇到高次幂相关问题时考虑快速幂

/*计算a的b次方*/
long long binpow(long long a,long long b)
{
long long res=1;
while(b>0)
{
if(b & 1)
res=res*a;
a=a*a;
b>>=1;
}
return res;
}

素数筛法——线筛

/*筛选出2-MAXN的素数*/
void init()
{
phi[1]=1;
for(int i=2;i<MAXN;++i)
{
if(!vis[i])
{
phi[i]=i-1;
pri[cnt++]=i;
}
for(int j=0;j<cnt;++j)
{
if(i*pri[j]>=MAXN)
break;
vis[i*pri[j]]=1;
if(i%pri[j])
{
phi[i*pri[j]]=phi[i]*(pri[j]-1);
}
else{
phi[i+pri[j]]=phi*pri[j];
break;
}
}
}
}

Day_2

前缀和

常出现于数列问题中

如求1 2 3 4 5 6 7数列中第2个-第6个的和

循环做法为2+3+4+5+6=20[i=l;i<r;i++]

前缀和进行预处理,将输入数组依次求和变为

1 2 6 10 15 21 28

则2-6的和为 21-1=20**[r-(l-1)]**

位运算

  1. & 与,两个都是1才为1
  2. | 或,有一个1就是1
  3. ^ 异或 不同时为1
  4. ~取反 0变1,1变0
  5. num << i 二进制表示左移i位
  6. num>> i 二进制表示右移i位

获取a的第b位:

int getBit(int a,int b)
{
return(a>>b)&1;
}

字符串哈希

将字符串变成一个p进制的数字

p=131或13331

string x;
p[0]=1;
h[0]=0;
for(int i=0;i<n;i++)
{
p[i+1]=p[i]*p;
h[i+1]=h[i]*p+x[i];
}

Day_3

二叉树

#include <bits/stdc++.h>
using namespace std;
typedef struct Node
{
int date;
struct Node *l_son;
struct Node *r_son;
Node():date(0),l_son(NULL),r_son(NULL){}
}node;
/// 新建节点
node* newNode(int val)
{
node* no = new node();
no->date = val;
return no;
}
void insert(node *root ,int x)
{
if( root == NULL )
{
root = newNode(x);
return ;
}
///建树规则
if( ... )
{
insert(root -> l_son , x );
}
else
{
insert(root -> r_son , x );
}
}
/// 更新、查找
void search(node* root,int x,int newdate)
{
if( root == NULL)
{
return ; /// 递归边界
}
if( root -> date == x)
{
root -> date = newdate;
return ;
}
search( root -> l_son , x , newdate );
search( root -> r_son , x , newdate );
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(0);
...
return 0;
}

树的遍历

层序遍历

void LayerOrder(node* root)
{
queue<node*> q;
q.push( root );
while( !q.empty() )
{
node* no =q.front();
q.pop();
cout << no -> date << endl;
if( now -> l_son != NULL )
{
q.push( no -> l_son );
}
else
{
q.push( no -> r_son );
}
}
}

先序遍历

void preOrder(node* root)
{
if(root == NULL)
{
return ;
}
cout << root->date<<endl;
preOrder(root -> l_ron);
preOrder(root -> r_son);
}

中序遍历

void inOrder(node* root)
{
if( root == NULL )
{
return ;
}
inOrder( root -> l_son );
cout << no -> daye << endl;
inOrder( root -> r_son );
}

后序遍历

void postOrder(node* root)
{
if( root == NULL )
{
return ;
}
postOrder( root -> l_son );
postOrder( root -> r_son );
cout << no -> daye << endl;
}

Day_4

并查集

并查集是一种树形结构,它用一棵树来表示一个集合,不同的集合其实就构成了一个
森林。
根据不同的需要添加格外的数组

//常用属性
p[i]//代表i的父节点
size[i]//代表i这个集合中有多少点
dis[i]//代表i到父节点的距离

初始化集合

for (int i = 1; i <= n; i ++ ){
p[i] = i;
size[i]=1;
dis[i]=0;
}

寻找祖宗节点

int find(int x)
{
if (p[x] != x)
{
int u = find(p[x]);//路径压缩
dis[x] += dis[p[x]];
p[x] = u;
}
return p[x];
}

合并集合(将a合并在b集合上)

void merge(int a,int b)
{
int pa=find(a);
int pb=find(b);
size[pb] += size[pa];
p[pa] = pb;
dis[pa] = distance;//根据具体问题描述偏移量
}

带权并查集(边的权值——用一个数组记录每个节点和其父节点的权值)

Day_5

线段树

区间类的问题经常使用

单点修改、单点查询、区间修改、
区间查询(区间求和,求区间最大值,求区间最小值)等

const int N = 1e5 + 5;
strcut Node
{
int l,r;
int sum;
}Tree[N>>2];

建树(push_up根据题意定)

void push_up(int rt)
{
Tree[rt].sum = Tree[rt << 1].sum + Tree[rt << 1|1].sum
}
void build(int rt,int l,int r)
{
Tree[rt].l = l , Tree[rt].r = r;
if( l == r )
{ /// 递归到了叶结点
Tree[rt].sum = A[r]; /// A为输入数组
return ;
}
int mid = l + r >> 1;
build( rt<<1 , l , mid );
build( rt<<1|1, mid + 1 , r );
push_up( rt );
}

单点更新

void update(int rt,int pos,int val)
{
/*如果找到*/
if( Tree[rt].l == Tree[rt].r )
{ /// 如果到了pos这个位置就更新
A[pos] +=val;
Tree[rt].sum +=val;
return ; /// 一定要return
}
/*寻找点*/
int mid = ( Tree[rt].l + Tree[rt].r ) >> 1;
if( pos <= mid ) update( rt << 1,pos,val );
/// 注意思考什么时候是if-else,什么时候是if-if
else update( rt << 1|1, pos, val );
push_up(rt); /// 更新父结点
}

单点查询

int update(int rt,int pos)
{
if( Tree[rt].l == Tree[rt].r )
{ /// 如果到了pos这个位置就更新
return Tree[rt].sum; /// 一定要return
}
int mid = ( Tree[rt].l + Tree[rt].r ) >> 1;
int res = 0;
if( pos <= mid ) res = update( rt << 1,pos );
/// 注意思考什么时候是if-else,什么时候是if-if
else res = update( rt << 1|1, pos );
return res;
}

区间查询

int update(int rt,int l,int r)
{
if( l <= Tree[rt].l && r >= Tree[rt].r )
{ /// 如果到了pos这个位置就更新
return Tree[rt].sum; /// 一定要return
}
int mid = ( Tree[rt].l + Tree[rt].r ) >> 1;
int res = 0;
if( l <= mid ) res += update( rt << 1,l,r );
/// 注意思考什么时候是if-else,什么时候是if-if
if( r > mid ) res += update( rt << 1|1, l,r );
return res;
}

lazy标记(push_down)

void push_down(int rt)
{
/// 如果lazy标记非空,我们就把标记下传
if( Tree[rt].lazy != 0 )
{
int mid = (Tree[rt].l + Tree[rt].r) >> 1;
/// 更新子节点
Tree[rt << 1].sum += Tree[rt].lazy * ( mid - Tree[rt].l + 1); /// 注意这后面
的值
Tree[rt << 1 | 1].sum += Tree[rt].lazy * ( Tree[rt].r - mid) ; /// 注意这后面
的值
/// 继续把标记下传
Tree[rt << 1].lazy += Tree[rt].lazy;
Tree[rt << 1|1].lazy += Treert].lazy;
/// 清空当前节点的lazy标记
Tree[rt].lazy = 0;
}
}

带标记下传的区间查询

ll rangeQuery(int rt,int l ,int r)
{
if( l <= Tree[rt].l && r >= Tree[rt].r )
{
return Tree[rt].sum;
}
ll mid = ( Tree[rt].l + Tree[rt].r ) >> 1;
push_down(rt); /// 标记下传
ll son = 0;
if( l <= mid ) son += rangeQuery(rt << 1,l,r); /// 查询左儿子
if( r > mid ) son += rangeQuery(rt << 1|1,l,r); /// 查询右儿子
push_up(rt);
return son;
}

带lazy标记的区间修改

void rangeUpdate(int rt, int l,int r,int val)
{
if( l <= Tree[rt].l && r >= Tree[rt].r )
{
Tree[rt].sum += val * (Tree[rt].r - Tree[rt].l + 1); /// 把所有的区间中的值都先修改
Tree[rt].lazy += val;
return ;
}
int mid = ( Tree[rt].l + Tree[rt].r ) >> 1;
push_down(rt); /// 标记下传
if( l <= mid ) rangeUpdate( rt << 1,l,r,val );
if( r > mid ) rangeUpdate( rt << 1|1,l,r,val );
push_up(rt); /// 区间值上传
}

本周感想

算法原理懂了但是在代码实现的时候很不顺畅于是越来越依靠板子,因为对算法实现所采用的每一步的过程,比如先做什么后做什么,用什么样的数据结构去做等等不太熟悉,其次由于之前没有接触这些方法,之前的思维一直都是暴力模拟,导致自己看到题的有些时候总想用最简单的if-else和多层循环等简单方法暴力模拟出来,而并不会去想这道题应该是哪一个部分的知识点,应该用那部分的算法知识去做等等,我觉得这是我目前的两个需要找到解决方法的地方。其实仔细想到就是因为对算法只是初步了解了,但并没有进行代码上的深层理解,如果做到此,应该能大幅缓解目前的问题所在。在后面的学习里考虑仔细想一下各个算法操作的每一行的代码实现是怎样的,将其过程在大脑中模拟出来。还有就是要注意那些题应该用哪方面的算法去求解,比如快速幂的题目就绝大多都和幂相关,遇到题目上的这些关键信息就要考虑使用这些算法。

最后

以上就是爱听歌铃铛最近收集整理的关于大一ACM暑假集训第二周学习总结的全部内容,更多相关大一ACM暑假集训第二周学习总结内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(57)

评论列表共有 0 条评论

立即
投稿
返回
顶部