当前位置: 首页 > news >正文

2025 -- 云智计划 -- 【CSP-S】模拟赛 #2_总结+题解

总结

T1

考场上有思路,并且把它码出来了,没有什么大问题。

T2

题二,考场上想到了一个分类讨论,但是没有用到并查集的一个做法。挂成了十分。主要是没有想到他在某一种情况继续要反转又不需要翻转即无解的情况。

T3

T3考场上去想查分去了,但是由于题目上面。发现差分会更具有普遍性,强于题目。这个时候我们就要去想一些更有针对性的做法。

题解

T1

我们会发现个位是最有可能会成为最优解的。因为它的变化速度是最快的。那么此时如果说我们的左边和右边差距超过了10。那么各位就已经完成了一次周期。那么此时的答案就一定是9。

如果说两个之间的差距小于九,那么直接枚举就可以了。

代码

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f3f3f3f3f
#define int long long
#define endl '\n'
using namespace std;
const int maxn=2e5+5;
int f(int x)
{int ans=-1;while(x) ans=max(ans,x%10),x/=10;return ans;
}
signed main()
{freopen("digit.in","r",stdin);freopen("digit.out","w",stdout);ios::sync_with_stdio(0);cin.tie(0); cout.tie(0);int t;cin>>t;while(t--){int l1,r1,l2,r2;cin>>l1>>r1>>l2>>r2;if(r1-l1+1>=10||r2-l2+1>=10) cout<<9<<endl;else{int ans=0;for(int i=l1;i<=r1;i++) for(int j=l2;j<=r2;j++) ans=max(ans,f(i+j));cout<<ans<<endl;}}return 0;
}

T2

我们发现最后每一列都至多是一,那么此时我们就可以发现。当前,这一列与它对称的这一列两个的两列的一的个数加起来,如果说大于二就一定不可能。

这里需要特判一下,如果说他对称的那一列就是他自己,那么等于二也不可以。

此时我们就看如果说当前当前这一行所对应的值所在的列。上还有一行的,这一列上也有值。那么他们俩就一定是要么一个翻转,一个不翻转。

如果说当年这一行所对应的值所在的列对称的那一个列上还有一行,这一列上也有值,那么这个时候一定是同时翻转或者同时不反转。(此时特判一下当前这一个还有的值是不是自己)

然后我们用种类并查集存他是否反转。如果说他翻转和不翻转在同一个集合内就不可以。否则我们设连通贯个数为 \(2k\),那么答案就是 \(2^k\)

代码

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f3f3f3f3f
#define int long long
#define endl '\n'
using namespace std;
const long long maxn=1e6+5,mod=1e9+7;
int fa[maxn],cnt[maxn];
int kasumi(int a,int b)
{if(b<0) return 0;int ans=1;while(b){if(b&1) ans=ans*a%mod;a=a*a%mod;b>>=1;}return ans;
}
void init(int n)
{for(int i=1;i<=n*2;i++) fa[i]=i;
}
int get(int x)
{return fa[x]==x?x:fa[x]=get(fa[x]);
}
void merge(int u,int v)
{u=get(u),v=get(v);if(u!=v) fa[v]=u;
}
signed main()
{freopen("reverse.in","r",stdin);freopen("reverse.out","w",stdout);ios::sync_with_stdio(0);cin.tie(0); cout.tie(0);int t;cin>>t;while(t--){int n,m;cin>>n>>m;init(n);for(int i=1;i<=m;i++) cnt[i]=0;int ans=n;vector<vector<int> > a(n+2);for(int i=1;i<=n;i++){a[i].resize(m+2);for(int j=1;j<=m;j++){char c;cin>>c;a[i][j]=c-'0';cnt[j]+=a[i][j];}}int f=1;if(m%2==1&&cnt[m/2+1]>=2) f=0;for(int j=1;j<=m/2;j++){if(cnt[j]>2) f=0;int x=0,y=0;for(int i=1;i<=n;i++){if(a[i][j]){if(x) y=i;else x=i;}}for(int i=1;i<=n;i++){if(a[i][m-j+1]){if(x) y=i;else x=i;}}if(!x||!y) continue;if(x==y) continue;if(a[x][j]==a[y][j]) merge(x,y+n),merge(x+n,y);else merge(x,y),merge(x+n,y+n);}int cnt=0;for(int i=1;i<=n*2;i++){if(i<=n&&get(i+n)==get(i)) f=0;if(fa[i]==i) cnt++;}cout<<f*kasumi(2,cnt/2)<<endl;}return 0;
}

T3

题目上有一个很重要且极具迷惑性的条件。\(a_i-a_{i-1}=1\)

这个条件是肯定是相当重要的。但是呢,我们会发现差分在这里就太强了。会导致我们这个代码更难写。我们发现他希望相邻的两个只差一,那么我们对每一个 \(a_i\) 减去 \(i\) 就可以了。

这样题目就被转化成每一次可以对一个值加一或者减一。最多做 \(k\) 次之后。最长相同的字段长度是多少?

这个值是可以双指针做的。那么我知道了一个区间如何快速计算它至少要操作多少次呢?

不难发现,我们每次都希望把这个区间内的值全部都变成这个区间内的中位数。那么我们用一个对顶堆求出中位数,然后再用区间内所有的数和减去这个中位数乘个数就可以了。

代码

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f3f3f3f3f
#define int long long
#define endl '\n'
using namespace std;
const int maxn=2e5+5;
int a[maxn];
signed main()
{freopen("subarray.in","r",stdin);freopen("subarray.out","w",stdout);ios::sync_with_stdio(0);cin.tie(0); cout.tie(0);int t;cin>>t;while(t--){int n,k;cin>>n>>k;multiset<int> q2;multiset<int,greater<int> > q1;for(int i=1;i<=n;i++) cin>>a[i],a[i]-=i;// for(int i=1;i<=n;i++) cout<<a[i]<<' ';// cout<<endl;int sum1=0,sum2=0,ans=0;for(int l=1,r=1;r<=n;r++){q1.insert(a[r]);sum1+=a[r];while(q1.size()>q2.size()) q2.insert(*q1.begin()),sum1-=*q1.begin(),sum2+=*q1.begin(),q1.erase(q1.begin());while(q1.size()<q2.size()) q1.insert(*q2.begin()),sum2-=*q2.begin(),sum1+=*q2.begin(),q2.erase(q2.begin());int cnt=sum2-q2.size()*(*q1.begin())+q1.size()*(*q1.begin())-sum1;while(cnt>k&&l<r){if(q1.find(a[l])!=q1.end()) q1.erase(q1.find(a[l])),sum1-=a[l];else q2.erase(q2.find(a[l])),sum2-=a[l];while(q1.size()>q2.size()) q2.insert(*q1.begin()),sum1-=*q1.begin(),sum2+=*q1.begin(),q1.erase(q1.begin());while(q1.size()<q2.size()) q1.insert(*q2.begin()),sum2-=*q2.begin(),sum1+=*q2.begin(),q2.erase(q2.begin());cnt=sum2-q2.size()*(*q1.begin())+q1.size()*(*q1.begin())-sum1;l++;// cout<<l<<' '<<r<<':'<<cnt<<endl;// cout<<*q1.begin()<<':'<<q1.size()<<' '<<sum1<<'|'<<q2.size()<<' '<<sum2<<endl;}ans=max(ans,r-l+1);// cout<<"sss"<<endl;}cout<<ans<<endl;// cout<<endl;}return 0;
}
http://www.vanclimg.com/news/1473.html

相关文章:

  • 使Excel高亮显示选中表格(使选中的表格更加突出)
  • 2、统计连续登录5天的用户
  • AMD纯NPU运行AI画图StableDiffusion3.0模型
  • C#自学笔记:委托与事件
  • 电流探头去磁与调零操作对测量精度的影响
  • 企业HR如何将AI Agent作为战略引擎重构业务流程
  • 7月29日总结
  • thradlocal
  • ThreadLocal线程隔离值为NULL,直接复制使用封装类
  • 基于 Nacos + Higress 的 MCP 开发新范式,手把手教程来了!
  • 使用Vue.js实现动态表单字段
  • 特征 - kkksc03
  • 7月29日
  • 图神经网络的未来与挑战
  • 网站SSL证书怎么选?不用SSL证书会怎么样?
  • 安全可靠的PolarDB V2.0 (兼容MySQL)产品能力及应用场景 - 王权富贵
  • 2025牛客暑期多校训练营5_J
  • 【LeetCode 24】力扣算法:两两交换链表中的节点
  • Pwn2Own柏林2025:第三天赛事成果与技术漏洞全记录
  • POLIR-Laws-民事诉讼法:手机录音能否作为民事诉讼证据?怎么录音才能被法院采信?
  • MCP是如何工作的?
  • OBS
  • 屏幕翻译 安卓app
  • 微算法科技(NASDAQ:MLGO)应用区块链联邦学习(BlockFL)架构,实现数据的安全传输
  • 星球助手发布更新 v1.7.0
  • 使用Spring Cloud和Resilience4j实现微服务容错与降级 - spiderMan1
  • WinForm自定义控件实现类似百度网盘客户端菜单组件
  • 【比赛记录】2025CSP-S模拟赛29
  • 树形dp练习
  • python中 命令行参数解析模块 argparse