暑假集训总结

集训经历

暑假集训伴随着最后一场百度之星个人赛的结束而结束,这一个多月的训练让我感受到了为自己目标而奋斗的满足感。
七月二十三号回到学校开始集训,在家里面完了大半个月,不得不说在家里面是真的很摆,一天哪怕是学了一个小时就感觉 哇!今天学的好充实啊^ - ^,所以说还是在学校训练的效果比较好。
到校第二天在机房打了场赛氪的全国大学生算法设计与编程挑战赛(夏季赛),第一次打这个比赛但是和我想象中的不太一样,懂得都懂。本来以为是拿不到奖了,没想到结果出来之后我们队也是银奖,不多说,懂得都懂。证书是挺不错的。
请添加图片描述
因为疫情原因我会校晚了一周,所以刚来的前两天任务量很大,边学新内容边补我没来的时候讲的内容。
集训每天都是上午九点到十一点一场手速赛,打完之后队长给我们讲一讲题,下午补一下题在温习一下前面学的内容,继续刷题比赛的时候大部分时间都是在罚坐(太菜了
训练的这一个月每天的训练赛加起来大概一百三十题左右,再加上自己刷题,刷刷自己学校OJ的题,打打牛客的比赛,还有几天一场的cf大概集训期间刷了两百五十道左右,训练量还是不小的,只是最后几天大家都累了,训练效率下来了,不然可能会更多。每天都是在刷题比赛训练学习新内容,过程虽然累但是结束了之后回头看却感觉很充实。集训最后百度之星的第二场还现学了主席树求区间前K大数和^ - ^,确实离谱嗷。

集训收获

在集训期间训练和学习了许多内容包括:

离散化处理

//储存所有离散化的值
vector<int>alls;
//排序
sort(alls.begin(),alls.end());
//去掉重复元素
alls.erase(unique(alls.begin(),alls.end()),alls.end());
//二分求出x对应的离散化的值
int find(int x)
{
    int l=0,r=alls.size()-1;
    while(l<r)
    {
        int min=l+r>>1;
        if(alls[mid]>=x)r=mid;
        else l=mid+1;
    }
    return r+1;
}

KMP

for(int i=2,j=0;i<=len2;i++)
    {
        while(j&&str[i]!=str[j+1])j=ne[j];
        if(str[i]==str[j+1])j++;
        ne[i]=j;
    }

Tire

void insert(char str[])
{
    int p=0;
    for(int i=0;str[i];i++)
    {
        int u=str[i]-'a';
        if(!son[p][u])son[p][u]=++idx;
        p=son[p][u];
    }
    cnt[p]++;
}
int query(char str[])
{
    int p=0;
    for(int i=0;str[i];i++)
    {
        int u=str[i]-'a';
        if(!son[p][u])return 0;
        p=son[p][u];
    }
    return cnt[p];
}

并查集

int find(int x)
{
    if(p[x]!=x)p[x]=find(p[x]);
    return p[x];
}

二分图匹配

bool find(int x)
{
    for(int i=h[x];i!=-1;i=ne[i])
    {
        int j=e[i];
        if(!st[j])
        {
            st[j]=true;
            if(match[j]==0||find(match[j]))
            {
                match[j]=x;
                return true;
            }
        }
    }
    return false;
}

树状数组

int lowbit(int x)//c[i]的区间长度
{
    return x&-x;
}

void add(int i,int x)//点更新,a[i]加上z
{
    for(;i<=n;i+=lowbit(i));//更新所有后继
    c[i]+=x;
}

int sum(int i)//求区间和
{
    int s=0;
    for(;i>0;i-=lowbit(i))//累加所有前驱
        s+=c[i];
    return s;
}

int sumn(int l,int r)
{
    return sum[r]-sum[l-1];
}

拓扑排序

bool topsort()
{
    int hh=0,tt=-1;

    for(int i=1;i<=n;i++)
        if(!d[i])
            q[++tt]=i;
    while(hh<=tt)
    {
        int t=q[hh++];
        for(int i=h[t];i!=-1;i=ne[i])
        {
            int j=e[i];
            d[j]--;
            if(d[j]==0)
                q[++tt]=j;
        }
    }
    return tt=n-1;
}

二分答案

最大值最小
    while(l<r)
    {
        int mid=l+r>>1;
        if(check(mid))r=mid;
        else l=mid+1;
    } 
最小值最大
    while(l+1<r)
    {
        int mid=l+r>>1;
        if(check(mid))l=mid;
        else r=mid;
    }

线段树

struct node{
    int l,r,mx;
}tree[N];
void build(int k,int l,int r)
{
    tree[k].l=l;
    tree[k].r=r;
    if(l==r)//找到了叶子节点
    {
        tree[k].mx=a[l];//树叶就等于a[i]
        return;
    }
    int mid=(l+r)/2;
    build(2*k,l,mid);//左子树
    build(2*k+1,mid+1,r);//右子树
    tree[k].mx=max(tree[k*2].mx,tree[k*2+1].mx);//递归更新线段区间最大值
}
void updata(int k,int i,int v)//点更新
{
    if(tree[k].l==tree[k].r&&tree[k].l==i)
    {
        tree[k].mx=v;
        return;
    }
    int mid=(tree[k].l+tree[k].r)/2;
    if(i<=mid)
        updata(2*k,i,c);
    else 
        updata(2*k+1,i,v);
    tree[k].mx=max(tree[2*k].mx,tree[2*k+1].mx);
}

最后一场个人赛现学的主席树

//theme:给定n个数,q次询问,每次求区间[l,r]中从小到大排序后第k个数。1 <= n <= 100 000, 1 <= q <= 5 000,1 <=l <=r<= n, 1 <= k <= j - i + 1
#include <iostream>
#include<cstdio>
#include<algorithm>
#define midd (l+r)/2
using namespace std;
typedef long long ll;
const int N = 200010;
int n, q, sz, cnt = 0;
int a[N], b[N], T[N];//a为原数组,b为排序离散化数组,T[i]为(值)[1,i]的根节点
int sum[N<<5], L[N<<5], R[N<<5];
 
inline int build(int l, int r)
{
    int rt = ++ cnt;
    sum[rt] = 0;
    if (l < r){
        L[rt] = build(l, midd);
        R[rt] = build(midd+1, r);
    }
    return rt;
}
 
inline int update(int pre, int l, int r, int x)
{
    int rt = ++ cnt;
    L[rt] = L[pre]; R[rt] = R[pre]; sum[rt] = sum[pre]+1;
    if (l < r){
        if (x <= midd) L[rt] = update(L[pre], l, midd, x);
        else R[rt] = update(R[pre], midd+1, r, x);
    }
    return rt;
}
 
inline int query(int u, int v, int l, int r, int k)//返回下标,即<=k个数
{
    if (l >= r) return l;
    int x = sum[L[v]] - sum[L[u]];
    if (x >= k) return query(L[u], L[v], l, midd, k);
    else return query(R[u], R[v], midd+1, r, k-x);
}
 
int main()
{
    while(scanf("%d%d", &n, &q)!=EOF){
        cnt=0;
        for (int i = 1; i <= n; i ++){
            scanf("%d", &a[i]);
            b[i] = a[i];
        }
        sort(b+1, b+1+n);
        sz = unique(b+1, b+1+n)-b-1;
        T[0] = build(1, sz);
        for (int i = 1; i <= n; i ++){
            int t = lower_bound(b+1, b+1+sz, a[i])-b;
            T[i] = update(T[i-1], 1, sz, t);
        }
        while (q --){
            int l, r, k;
            scanf("%d%d%d", &l, &r ,&k);
           // k= r-l+1-k+1;//求第k大时改一下就行
           int idx=query(T[l-1], T[r], 1, sz, k);
            int ans=b[idx];
            printf("%d\n",ans);
        }
    }
    return 0;
}

还有DFS、BFS、状压DP、环状DP、多源BFS、多源DFS、双端队列、双向广搜、迭代加深等内容,
经过集训收获了许多的东西。
从一开始见到题目就发愁想不出来怎么写,慢慢的到见到题目之后知道这个题目考察的是什么知识点,感觉慢慢的打开了算法世界的大门,我感觉这是一种心态的转变也是成长。在机房里学长还有队友每天都在努力的训练,这种氛围一直在推动着我们每一个人在算法的道路上继续前进。自己现在的水平自己内心很清楚,我也更清楚的认识到了自己跟强者之间的差距,距离是慢慢拉出来的。还得继续加练,不断变强。通过这次暑假集训,我们也充分意识到了和别人们的差距,也算是开阔了眼界。而且也学到了不少新知识,动态规划,图论,和一些数论的知识,也充分意识到了学好数学是多么重要。竞赛之路还很长,现在只是开始,后面还有数不尽的困难在等着我们,但是我也并不气馁,千里之行始于足下,现在就要开始加把劲了。自信来源于训练!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值