首页 > 其他分享 >暑假集训CSP提高模拟3

暑假集训CSP提高模拟3

时间:2024-07-24 20:55:40浏览次数:13  
标签:bin int mid 集训 -- 暑假 llt CSP best

暑假集训CSP提高模拟3


2/35 反向挂了若干分又正向挂了若干

T1 abc猜想

水,随便变形推个柿子糊个快速幂就好了

T2 简单的排列最优化题

考虑只计算每次右移的 \(delta\),我们发现一个点只会在到贡献为 \(0\) 的位置和序列开头会改变对 \(delta\) 的贡献,直接算就好,\(O(n)\) 的

T3 简单的线性做法题

难题,赛时写暴力套了个卡时怒艹 \(85\)

考虑两个部分分之间可以根号分治。

再考虑一个分治,直接从分治中心暴力扩展,两边扫一遍统计出可能的值(可以证明整个区间的绝对众数一定等于两边某一前(后)缀的众数)

枚举这个可能的答案,可以证明只有 \(O(\log n)\) 个,之后开个桶,记录每个右区间可以和几个左区间拼合就好了,需要前缀和优化,加上分治,复杂度 \(O(n \log^2 n)\),不过貌似有线性做法

贴个代码

#include<bits/stdc++.h>
#define llt long long
const llt N=1001000;
using namespace std;
llt n,s[N],bin[N],us[N],ans;vector<llt> vec;bool vis[N];
void solve(llt l,llt r)
{
    if(l==r)    {ans++;return;}
    vector<llt>().swap(vec);
    llt mid=l+r>>1,best=0,len;
    for(int i=mid;i>=l;i--)
    {
        bin[s[i]]++;
        if(bin[s[i]]>bin[best])  best=s[i];
        if(vis[best]==0)    vec.push_back(best),vis[best]=1;
    }
    for(int i=mid;i>=l;i--) bin[s[i]]--;
    for(int i=mid+1;i<=r;i++)
    {
        bin[s[i]]++;
        if(bin[s[i]]>bin[best])  best=s[i];
        if(vis[best]==0)    vec.push_back(best),vis[best]=1;
    }
    for(int i=mid+1;i<=r;i++) bin[s[i]]--;
    len=vec.size();
    for(int j=0;j<len;j++)
    {
        vis[vec[j]]=0;
        for(int i=mid;i>=l;i--)
            bin[s[i]]++,us[bin[vec[j]]*2-mid+i-1+mid-l+1]++;
        for(int i=(mid-l+1)*2;i>=0;i--) us[i]+=us[i+1];
        for(int i=mid;i>=l;i--) bin[s[i]]--;
        for(int i=mid+1;i<=r;i++)   bin[s[i]]++,ans+=us[(i-mid)-2*bin[vec[j]]+mid-l+1+1];
        for(int i=mid+1;i<=r;i++) bin[s[i]]--;
        for(int i=(mid-l+1)*2;i>=0;i--) us[i]=0;
    }
    solve(l,mid);solve(mid+1,r);
}
int main()
{
    #ifdef LOCAL 
        freopen("1.in","r",stdin);
        freopen("1.out","w",stdout);
    #endif
    scanf("%lld",&n);
    for(int i=1;i<=n;i++)   scanf("%lld",&s[i]);
    solve(1,n);
    printf("%lld\n",ans);
    return 0;
}

T4 简单的线性做法题

简单题,考虑每个数最多只会被开 \(6\) 次,暴力修改即可,可以用势能线段树或者并查集找到区间第一个可以修改的值# 暑假集训CSP提高模拟3


2/35 反向挂了若干分又正向挂了若干

T1 abc猜想

水,随便变形推个柿子糊个快速幂就好了

T2 简单的排列最优化题

考虑只计算每次右移的 \(delta\),我们发现一个点只会在到贡献为 \(0\) 的位置和序列开头会改变对 \(delta\) 的贡献,直接算就好,\(O(n)\) 的

T3 简单的线性做法题

难题,赛时写暴力套了个卡时怒艹 \(85\)

考虑两个部分分之间可以根号分治。

再考虑一个分治,直接从分治中心暴力扩展,两边扫一遍统计出可能的值(可以证明整个区间的绝对众数一定等于两边某一前(后)缀的众数)

枚举这个可能的答案,可以证明只有 \(O(\log n)\) 个,之后开个桶,记录每个右区间可以和几个左区间拼合就好了,需要前缀和优化,加上分治,复杂度 \(O(n \log^2 n)\),不过貌似有线性做法

贴个代码

#include<bits/stdc++.h>
#define llt long long
const llt N=1001000;
using namespace std;
llt n,s[N],bin[N],us[N],ans;vector<llt> vec;bool vis[N];
void solve(llt l,llt r)
{
    if(l==r)    {ans++;return;}
    vector<llt>().swap(vec);
    llt mid=l+r>>1,best=0,len;
    for(int i=mid;i>=l;i--)
    {
        bin[s[i]]++;
        if(bin[s[i]]>bin[best])  best=s[i];
        if(vis[best]==0)    vec.push_back(best),vis[best]=1;
    }
    for(int i=mid;i>=l;i--) bin[s[i]]--;
    for(int i=mid+1;i<=r;i++)
    {
        bin[s[i]]++;
        if(bin[s[i]]>bin[best])  best=s[i];
        if(vis[best]==0)    vec.push_back(best),vis[best]=1;
    }
    for(int i=mid+1;i<=r;i++) bin[s[i]]--;
    len=vec.size();
    for(int j=0;j<len;j++)
    {
        vis[vec[j]]=0;
        for(int i=mid;i>=l;i--)
            bin[s[i]]++,us[bin[vec[j]]*2-mid+i-1+mid-l+1]++;
        for(int i=(mid-l+1)*2;i>=0;i--) us[i]+=us[i+1];
        for(int i=mid;i>=l;i--) bin[s[i]]--;
        for(int i=mid+1;i<=r;i++)   bin[s[i]]++,ans+=us[(i-mid)-2*bin[vec[j]]+mid-l+1+1];
        for(int i=mid+1;i<=r;i++) bin[s[i]]--;
        for(int i=(mid-l+1)*2;i>=0;i--) us[i]=0;
    }
    solve(l,mid);solve(mid+1,r);
}
int main()
{
    #ifdef LOCAL 
        freopen("1.in","r",stdin);
        freopen("1.out","w",stdout);
    #endif
    scanf("%lld",&n);
    for(int i=1;i<=n;i++)   scanf("%lld",&s[i]);
    solve(1,n);
    printf("%lld\n",ans);
    return 0;
}

T4 简单的线性做法题

简单题,考虑每个数最多只会被开 \(6\) 次,暴力修改即可,可以用势能线段树或者并查集找到区间第一个可以修改的值,赛时被卡常了

标签:bin,int,mid,集训,--,暑假,llt,CSP,best
From: https://www.cnblogs.com/hzoi-wang54321/p/18321715

相关文章

  • [题解]P9755 [CSP-S 2023] 种树
    P9755[CSP-S2023]种树迟来的补题本题是让最小化所有树长到指定高度日期的最大值,于是想到二分答案。那么,对于一个给定的期限\(x\),如何判断是否能在这个日期内完成任务呢?首先我们发现前\(n\)天每天都要种树,那么假设我们已经知道了每个地块最晚哪个日期种树,能保证在期限\(x\)......
  • ssy学校暑假集训游记
    7.24日集训第二天不要问为什么第二天才写,这不重要。上午模拟赛,先开T1订正......T1先引入逆序对,如果有$1$在$0$前面,就算一组逆序对。对于这个题,很容易可以猜想出最后的结果$000....0011..11$。回看题目中所给的条件,无论是$10$,$100$,$110$还是$1010$,他翻转过去一定能减少......
  • 24暑假算法刷题 | Day20 | LeetCode 235. 二叉搜索树的最近公共祖先,701. 二叉搜索树中
    目录235.二叉搜索树的最近公共祖先题目描述题解701.二叉搜索树中的插入操作题目描述题解450.删除二叉搜索树中的节点题目描述题解235.二叉搜索树的最近公共祖先点此跳转题目链接题目描述给定一个二叉搜索树,找到该树中两个指定节点的最近公共祖先。百度......
  • 24暑假算法刷题 | Day21 | LeetCode 669. 修剪二叉搜索树,108. 将有序数组转换为二叉搜
    目录669.修剪二叉搜索树题目描述题解108.将有序数组转换为二叉搜索树题目描述题解538.把二叉搜索树转换为累加树题目描述题解669.修剪二叉搜索树点此跳转题目链接题目描述给你二叉搜索树的根节点root,同时给定最小边界low和最大边界high。通过修剪二叉......
  • 『模拟赛』暑假集训CSP提高模拟6
    RankA.花间叔祖签到题,但没切。一眼出思路找最大公因数,过了大样例发现同余的情况也合法,然后开始优化,成功从68pts到了88pts。考虑正解,首先答案不是一就是二。若答案是一,即所有数可在模某数\(x\)意义下同余。不妨将每个数化成\(a_i=k\timesx+d\)的形式,则若存在一个......
  • 2024暑假集训总结
    2024暑假集训总结知识点清单:树状数组拓展:(1)k维前缀和(2)树状数组+倍增没码过,小慌线段树:(1)线段树不仅仅是一个维护区间和、区间最值或者类似于方差那道题,维护区间的平方等等信息,它的深层是将区间拆分为\(O(logn)\)个子区间从而将修改与查询降为\(O(logn)\)级别,因此对于线......
  • 2024 暑假集训
    树状数组&线段树线段树合并,主席树等知识点是第一次接触。同时对扫描线能解决的问题有了些更好的认知。毕竟是之前学过的东西,还是比较好的。掌握程度:\(85\%^+\)离线分治算法具体是:线段树分治\(80\%^+\)就是个线段树上二分。CDQ分治基于时间的分治\(75\%^+\)基本......
  • [2024JZYZ暑期集训]知识点总结
    前言第三次暑期集训了,与前两次不同,这次没有前两次的激动了,所以也能够更深入地学习算法。闲话宿舍挺好,有空床能住。捡了三块钱,史上最灵异事件。R班好热闹。认识了几个郑州那边的大佬知识点Day1讲了几个基础数据结构(树状数,线段树),作业里面的题目很多之前都做过,就当复习了。......
  • 2024年pt市S组暑假集训游记
    记录而已,不必在意Day1上午第一天,一中的lzy老师把我们分配到一楼的机房,好,有沙发,有三个大空调,听说原来是一中的监控室。结果,我们去6楼等了好久,还是没有开课,然后我们就被叫去5楼听课了,火大。幸好听完课之后还是去一楼机房耍,开心。老师上课给我们复习了一些基础的东西,这......
  • csp提高模拟6
    赛时rank13,T1100,T210,T357,T40花间叔祖原题链接水题。考虑答案可能为1或2。假设所有的数都可以表示为\(am+1\),那么答案就是1,反之为0。将差求gcd,若为1,则答案为2,反之为1.点此查看代码#include<bits/stdc++.h>#include<bits/extc++.h>#defineCAIint#definecailong......