首页 > 其他分享 >『模拟赛』暑假集训CSP提高模拟17

『模拟赛』暑假集训CSP提高模拟17

时间:2024-08-10 17:39:31浏览次数:15  
标签:ch 17 int qr 模拟 define CSP lx fo

Rank

image

A. 符号化方法初探

原[ABC081D] Non-decreasing

挺水的,不过赛时想了错解。

赛时做法是都塞到一个 set 里一遍推过去,如果比上一个小就 lower_bound 找一个最接近差的数加上,不过它存在比较大的问题。

首先全是负判不了,会进入死循环;其次用 map 存下标也会出现存在两个相同的值,一个替换另一个后值更改,此时找到的下标对应的值并不是我们想要的值。

但是还是对他抱一些希望,如果有能调出来的大佬请帮忙看下感谢qwq。

赛时代码

更改前

#include<bits/stdc++.h>
#define fo(x,y,z) for(register int (x)=(y);(x)<=(z);(x)++)
#define fu(x,y,z) for(register int (x)=(y);(x)>=(z);(x)--)
using namespace std;
typedef long long ll;
#define lx int
inline lx qr()
{
	char ch=getchar();lx x=0,f=1;
	for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
	for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<3)+(x<<1)+(ch^48);
	return x*f;
}
#undef lx
#define qr qr()
const int Ratio=0;
const int N=1e5+5;
int n,m;
ll a[N];
ll q1[N],q2[N];
map<ll,ll>mp;
set<ll>st;
set<ll>::iterator it;
namespace Wisadel
{
    short main()
    {
        // freopen(".in","r",stdin),freopen(".out","w",stdout);
        n=qr;
        fo(i,1,n) a[i]=qr,st.insert(a[i]),mp[a[i]]=i;
        fo(i,2,n)
        {
            while(a[i]<a[i-1])
            {
                it=st.lower_bound(a[i-1]-a[i]);
                if(it==st.end()) --it;
                q1[++m]=mp[*it],q2[m]=i;
                st.erase(a[i]);
                a[i]+=*it;
                st.insert(a[i]);
                mp[a[i]]=i;
            }
        }
        printf("%d\n",m);
        fo(i,1,m)
            printf("%lld %lld\n",q1[i],q2[i]);
        return Ratio;
    }
}
int main(){return Wisadel::main();}

更改后

#include<bits/stdc++.h>
#define fo(x,y,z) for(register int (x)=(y);(x)<=(z);(x)++)
#define fu(x,y,z) for(register int (x)=(y);(x)>=(z);(x)--)
using namespace std;
typedef long long ll;
#define lx int
inline lx qr()
{
	char ch=getchar();lx x=0,f=1;
	for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
	for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<3)+(x<<1)+(ch^48);
	return x*f;
}
#undef lx
#define qr qr()
const int Ratio=0;
const int N=1e5+5;
int n,m;
ll a[N];
ll q1[N],q2[N];
map<ll,ll>mp;
set<ll>st;
set<ll>::iterator it;
namespace Wisadel
{
    short main()
    {
        // freopen(".in","r",stdin),freopen(".out","w",stdout);
        n=qr;
        ll maxx=-1e9,minn=1e9;
        fo(i,1,n) a[i]=qr,st.insert(a[i]),mp[a[i]]=i,maxx=max(maxx,a[i]),minn=min(minn,a[i]);
        if(maxx+minn>0)
        {
            fo(i,2,n)
            {
                while(a[i]<a[i-1])
                {
                    it=st.lower_bound(a[i-1]-a[i]);
                    if(it==st.end()) --it;
                    q1[++m]=mp[*it],q2[m]=i;
                    st.erase(a[i]);
                    a[i]+=*it;
                    st.insert(a[i]);
                    mp[a[i]]=i;
                }
            }
        }
        else
        {
            fu(i,n-1,1)
            {
                // cout<<i<<' '<<i+1<<":"<<a[i]<<' '<<a[i+1]<<endl;
                while(a[i]>a[i+1])
                {
                    // cout<<i<<' '<<a[i]<<' '<<a[i+1]<<endl;
                    it=st.lower_bound(a[i+1]-a[i]);
                    if(a[i+1]-a[i]!=*it&&it!=st.begin()) --it;
                    // cout<<"$%^&*(&^%$#)"<<*it<<' '<<mp[*it]<<endl;
                    q1[++m]=mp[*it],q2[m]=i;
                    st.erase(a[i]);
                    a[i]+=*it;
                    st.insert(a[i]);
                    mp[a[i]]=i;
                }
            }
        }
        printf("%d\n",m);
        fo(i,1,m)
            printf("%lld %lld\n",q1[i],q2[i]);
        return Ratio;
    }
}
int main(){return Wisadel::main();}

正解是若全不为负就 n-1 次碾过去,每次让 i 加上前一个的值;若全不为正就倒序同上;否则比较极值的绝对值大小,最大值的较大就让所有除最大值外的数加上最大值,然后同情况 1,最小值的较大就让所有除最小值外的数加上最小值,然后同情况 2。

点击查看代码
#include<bits/stdc++.h>
#define fo(x,y,z) for(register int (x)=(y);(x)<=(z);(x)++)
#define fu(x,y,z) for(register int (x)=(y);(x)>=(z);(x)--)
using namespace std;
typedef long long ll;
#define lx int
inline lx qr()
{
	char ch=getchar();lx x=0,f=1;
	for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
	for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<3)+(x<<1)+(ch^48);
	return x*f;
}
#undef lx
#define qr qr()
const int Ratio=0;
const int N=2e5+5;
const int mod=998244353;
int n,m;
struct rmm
{
    ll x,id;
}a[N];
bool cmp(rmm a,rmm b){return a.x<b.x;}
namespace Wisadel
{
    short main()
    {
        // freopen(".in","r",stdin),freopen(".out","w",stdout);
        n=qr;
        fo(i,1,n) a[i].x=qr,a[i].id=i;
        sort(a+1,a+1+n,cmp);
        if(a[1].x>=0)
        {
            printf("%d\n",n-1);
            fo(i,1,n-1) printf("%d %d\n",i,i+1);
        }
        else if(a[n].x<=0)
        {
            printf("%d\n",n-1);
            fu(i,n,2) printf("%d %d\n",i,i-1);
        }
        else
        {
            printf("%d\n",2*n-2);
            if(abs(a[1].x)<=a[n].x)
            {
                fo(i,1,n) if(i!=a[n].id) printf("%d %d\n",a[n].id,i);
                fo(i,1,n-1) printf("%d %d\n",i,i+1);
            }
            else
            {
                fo(i,1,n) if(i!=a[1].id) printf("%d %d\n",a[1].id,i);
                fu(i,n,2) printf("%d %d\n",i,i-1);
            }
        }
        return Ratio;
    }
}
int main(){return Wisadel::main();}

B. 无标号 Sequence 构造

原[GDKOI2023 提高组] 矩阵

一道非常有学习意义的题。

一眼脑残题,然后看到数据范围 \(n\le 3000\) 蒙了,没想到什么好办法,所以还是 \(\mathcal{O(n^3)}\) 硬莽拿下 50pts。

正解是随机一个 \(1\times n\) 的矩阵,这样就缩小了矩阵相乘的规模,从而将复杂度降低到 \(\mathcal{O(N^2)}\) 级别。

写了篇题解求赞捏。

点击查看代码
#include<bits/stdc++.h>
#define fo(x,y,z) for(register int (x)=(y);(x)<=(z);(x)++)

const int Ratio=0;
const int N=3e3+5;
const int mod=998244353;
int T,n;
int a[N][N],b[N][N],c[N][N],d[2][N],e[2][N],f[2][N],g[2][N];
namespace Wisadel
{
    short main()
    {
        scanf("%d",&T);srand(time(0));
        while(T--)
        {
            scanf("%d",&n);bool can=1;
            fo(i,1,n) fo(j,1,n) scanf("%d",&a[i][j]);
            fo(i,1,n) fo(j,1,n) scanf("%d",&b[i][j]);
            fo(i,1,n) fo(j,1,n) scanf("%d",&c[i][j]);
            fo(i,1,n) d[1][i]=rand(),e[1][i]=0,f[1][i]=0,g[1][i]=0;
            fo(j,1,n) fo(k,1,n) e[1][j]=(e[1][j]+1ll*d[1][k]*a[k][j]%mod)%mod;
            fo(j,1,n) fo(k,1,n) f[1][j]=(f[1][j]+1ll*e[1][k]*b[k][j]%mod)%mod;
            fo(j,1,n) fo(k,1,n) g[1][j]=(g[1][j]+1ll*d[1][k]*c[k][j]%mod)%mod;
            fo(i,1,n) if(f[1][i]!=g[1][i]){can=0;break;}
            printf(can?"Yes\n":"No\n");
        }
        return Ratio;
    }
}
int main(){return Wisadel::main();}

C. 无标号 Multiset 构造

需要先打半个小时表预处理出来不同的 m 值,所以只拿了 5pts 的样例分。

D. 有限制的构造

原[ABC364E] Maximum Glutton

也很有学习意义的一题。

如果不看数据范围,是一个很经典的二维费用背包问题,\(f_{i,j,k}\) 表示到第 \(i\) 个游戏,画质和为 \(j\),不可玩度为 \(k\) 最多选几个游戏,最终答案为 \(f_{n,A,B}\),当然第一维完全可以省略。

但是,这道题两个费用的上线都是 \(10^4\) 级别的,空间上就算省掉了一维复杂度还是 \(\mathcal{O(n^2)}\),就算开 short 也无法承受,时间复杂度为 \(\mathcal{O(nV^2)}\) 同样无法实现。

所以需要转换思路。

首先一种,因为 \(n\le 80\) 范围极小,所以我们可以选择退火,(但是不会所以不考虑。

第二,我们可以交换一维 dp 数组的维度,将范围较小的值域计入一维,将范围较大的费用计入值域,此时我们的 dp 数组的含义变成了:\(f_{i,j,k}\) 表示到第 \(i\) 个游戏,玩了 \(j\) 个,画质和为 \(k\) 时的最小不可玩度。这样一来,我们的空间复杂度和时间复杂度都变为了 \(\mathcal{O(n^2V)}\),最后统计答案只需要倒序遍历一遍 \(j\) 维找到值满足 \(\le B\) 的即可。

还要注意的一点,我们可以最后超出界限一个游戏,想象一下就是:背包目前塞不下一个物品,我们可以敞口再放一个。不过这样的前提是 \(n\) 个游戏没有全部都玩(致敬 lxyt

点击查看代码(未优化,开 short 过的)
#include<bits/stdc++.h>
#define fo(x,y,z) for(register int (x)=(y);(x)<=(z);(x)++)
#define fu(x,y,z) for(register int (x)=(y);(x)>=(z);(x)--)
using namespace std;
typedef long long ll;
#define lx int
inline lx qr()
{
	char ch=getchar();lx x=0,f=1;
	for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
	for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<3)+(x<<1)+(ch^48);
	return x*f;
}
#undef lx
#define qr qr()
const int Ratio=0;
const int N=1e4+5;
int n,A,B;
short a[N],b[N],f[88][88][N];
namespace Wisadel
{
    short main()
    {
        // freopen(".in","r",stdin),freopen(".out","w",stdout);
        n=qr,A=qr,B=qr;
        fo(i,1,n) a[i]=qr,b[i]=qr;
        memset(f,0x3f,sizeof f);
        fo(i,0,n) f[i][0][0]=0;
        fo(i,1,n) fo(j,1,i) fo(k,0,A)
        {
            if(k>=a[i]) f[i][j][k]=min(f[i][j][k],short(f[i-1][j-1][k-a[i]]+b[i]));
            f[i][j][k]=min(f[i][j][k],f[i-1][j][k]);
        }
        fu(i,n,0) fo(j,0,A) if(f[n][i][j]<=B)
        {
            printf("%d\n",i+(i!=n));
            return Ratio;
        }
        return Ratio;
    }
}
int main(){return Wisadel::main();}

这次也是收获很多的一场模拟赛啊,能学到很多专题里学不到的小细节。

博客写到 T4 差点坠机了,还好 yuen 告诉我博客园有自动备份,感谢博客园!同时感谢在榜首把我的分块莫队挂了两天!

赛时一直受困于在线测评的 sb 机制:超过给定内存的一半自动 RE,导致我卡在 T2 一个小时,最后还被迫改小了数组,(虽然改不改一个分。


完结撒花~

另外

\(\Huge{七夕节快乐!}\)

\(\small{能在学 OI 时找到另一半吗www}\)

标签:ch,17,int,qr,模拟,define,CSP,lx,fo
From: https://www.cnblogs.com/Ratio-Yinyue1007/p/18352557

相关文章

  • 【大作业-17】使用TensorFlow快速实现图像风格迁移系统
    使用TensorFlow快速实现图像风格迁移系统资源地址:28-基于Tensorflow的风格迁移+代码+模型+系统界面+教学视频.zip资源-CSDN文库视频地址:[使用Tensorflow实现图像风格迁移系统_哔哩哔哩_bilibili](https://www.bilibili.com/video/BV1VE421w7RY/)随着GPT的横空出世,生成......
  • springboot垂钓服务系统-计算机毕业设计源码17434
    摘要本文旨在针对垂钓爱好者的需求,基于微信小程序平台,设计并实现一套垂钓服务系统。首先,通过对用户需求进行调研和分析,确定了系统的基本功能模块,包括垂钓点信息展示、用户预约和支付、钓具租赁信息等。接着,借助微信小程序提供的开发框架和组件库,实现了系统的界面设计和交互功......
  • 常见 字符串库函数 的使用与模拟实现 #strlen #strcpy #strcat #strcmp#strstr #strto
    文章目录前言路漫漫其修远兮,吾将上下而求索。在C语言之中,提供了字符类型,也有字符串的概念,但是却并没有字符串的类型。没有类型就不方便操作,于是乎就提供了一系列的字符串函数来支持对字符串的操作;一、求字符串长度strlen专门用来求字符串长度的函数size_t strl......
  • 暑假集训CSP提高模拟17
    暑假集训CSP提高模拟17组题人:@joke3579\(T1\)P222.符号化方法初探\(70pts\)原题:[ABC081D]Non-decreasing部分分测试点\(1\):输出样例\(1\)。测试点\(11\sim15\):由于\(\{a\}\)非负,所以对\(\{a\}\)作前缀和即可。随机\(pts\):乱搞。正解当......
  • P9750 [CSP-J 2023] 一元二次方程题目总结
    根据题面,我们将分为多种情况讨论:若a为负数,那么将a,b,c全部取反首先求出data=b^2-4*a*c;1,data<=0cout<<”NO”;否则带入求跟公式:-b/2a+(-)sqrt(data)注意::gcd(a,b)有可能为负数,此处应用abs(x)取绝对值若开根号data为有理数{-b为2*a的倍数则直接输出b否则输出b/gcd(b,2*a......
  • 升级到iOS 18、降级回iOS 17
    热烈欢迎,请直接点击!!!进入博主AppStore主页,下载使用各个作品!!!注:博主将坚持每月上线一个新app!! 苹果官方下载链接:【操作系统OperatingSystems】:https://developer.apple.com/download/【应用Applications】:https://developer.apple.com/download/applications/【描述文件Pr......
  • P1725 琪露诺 题解
    思路动态规划,单调队列动态规划观察题目,发现下标为\(i\)的点只能对\([i+l,i+r]\)区间的点产生贡献。设\(f_i\)为到达点\(i\)时的最大冻结指数。易得状态转移方程式:\(f_k\leftarrow\max(f_k,f_i+a_k),(k\in[i+l,i+r])\)。若直接对该方程进行转移,时间复......
  • strlen求字符串长度 模拟实现strlen函数 strcpy函数 模拟实现strcpy strcat函数 模拟
    文章目录1.1strlen求字符串长度1.2模拟实现strlen函数2.1strcpy函数2.2模拟实现strcpy3.1strcat函数3.2模拟实现strcat1.1strlen求字符串长度strlen是一个库函数所包含的头文件为#include<string.h>,这里我们可以在Cplusplus上找到strlen所包含的头文件以及strlen......
  • 使用HTML一键打包工具模拟其他浏览器 - User-Agent的起源到应用
    最近经常有一些朋友对于HTML一键打包工具中的User-Agent不太理解是什么意思,以及它到底有什么用途, 本篇文章会介绍一下User-Agent的起源,发展历程,以及它的使用场景,帮助你更好的了解和使用它User-Agent的起源与发展历程User-Agent最早出现在1990年代初期,随着NCSAMosaic......
  • “斯诺克”不等于“台球”-《分析模式》漫谈17
    DDD领域驱动设计批评文集做强化自测题获得“软件方法建模师”称号《软件方法》各章合集“AnalysisPatterns”的第一章有这么一句:Considersomeonewhowantstowritesoftwaretosimulatea game of snooker. 2004(机械工业出版社)中译本的译文为: game翻译成“游......