2025 1.18-1.26 week 1
1.18-1.26 week 1
-
前言
-
补题
- SMU Winter 2025 Round 1
- SMU Winter 2025 Round 2
- SMU Winter 2025 Round 3
-
总结
1.前言
一些问题:
涉及卡时间复杂度的题目不能很好的优化
二分和dp的不熟练
赛时心态和耐心的不足
另外4和5放到下周或者有时间我会补到这次周报的TT
2.补题
1.SMU Winter 2025 Round 1
D.Lost Permutation
题意:找出任意个和等于s的数,这些数可以与测试点给出的数形成排列(如果一个序列包含从1到n的所有整数,且每个整数只出现一次,则称其为排列)。
思路:先找出所有空缺的数,看看给出的s能否填满空缺;在填满空缺后,判断他能否用剩下的数正好将排列扩大,能够全用完就YES,反之NO。
#include<bits/stdc++.h> using namespace std; #define int long long void solve(){ int m,s;cin>>m>>s; int arr[m+5]={0},count=0; for(int i=0;i<m;i++){ cin>>arr[i]; } sort(arr,arr+m); int isuse[arr[m-1]+5]={0}; for(int i=0;i<m;i++){ isuse[arr[i]]++; } for(int i=1;i<=arr[m-1];i++){ if(isuse[i]==0){ count+=i; } } if(count>s){ cout<<"NO\n";return; } else{ s-=count; int temp=arr[m-1]+1; while(s>0){ s-=temp; temp++; } if(s==0){ cout<<"YES\n";return; }else cout<<"NO\n";return; } } signed main() { ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); int t;cin>>t; while(t--){ solve(); } return 0; }
F.Thermostat
题意:温度的范围从l到r,你需要求从a到b最少调节几次温度(a与b在l到r之间),每一次温度变化不能少于x。存在无法实现的情况。
思路:有五种情况。无解:a上调或下调均不能大于等于x,b也同理;0解:a=b;1解: ∣a−b∣≥x;2解:触一次边界再到b;3解:触两次边界到b。
#include<bits/stdc++.h> using namespace std; #define int long long void solve(){ int l,r,x,a,b; cin>>l>>r>>x>>a>>b; if(a==b) printf("0\n"); else if(abs(a-b)>=x) printf("1\n"); else if((b-l<x&&r-b<x)||(a-l<x&&r-a<x)||r-l<x) printf("-1\n"); else if((r-a>=x&&r-b>=x)||(a-l>=x&&b-l>=x)) printf("2\n"); else printf("3\n"); } signed main() { ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); int t;cin>>t; while(t--){ solve(); } return 0; } L.XOR = Average
题意:找n个数,他们依次按位异或的结果等于其平均数。
思路:奇数个1异或之后还是1;对于偶数,可以用n个2,将其中两个2换成1和3,这样他们的平均数就是2 且 1与3异或为2,n-1个2异或之后还是2。
#include<bits/stdc++.h> using namespace std; #define int long long void solve(){ int n;cin>>n; if(n%2!=0){ for(int i=0;i<n;i++){ cout<<1<<" "; } cout<<endl; }else{ for(int i=0;i<n-2;i++){ cout<<2<<" "; } cout<<"1 3\n"; } } signed main() { ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); int t;cin>>t; while(t--){ solve(); } return 0; }
2.SMU Winter 2025 Round 2
E.Eating Queries
题意:有n个数,问至少多少个数的和能不小于x。
思路:从大到小排列之后求前缀和然后二分找大于等于x的部分,可用lower_bound。
#include<bits/stdc++.h> using namespace std; const int N=15e4+5; #define int long long bool cmp(int a,int b){ return a>b; } void solve(){ int n,q,x,ans,a[N]; cin>>n>>q; for(int i=1;i<=n;i++)cin>>a[i]; sort(a+1,a+n+1,cmp); for(int i=1;i<=n;i++)a[i]+=a[i-1]; while(q--){ cin>>x; ans=lower_bound(a+1,a+n+1,x)-a; if(ans<=n)cout<<ans<<endl; else cout<<"-1\n"; } } signed main() { ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); int t;cin>>t; while(t--){ solve(); } return 0; }注:`lower_bound(a + 1, a + n + 1, x) `返回的是指针,减去数组 的起始地址 a才能得到偏移量,也就是元素的下标。
3.SMU Winter 2025 Round 3
E.Array Decrements
题意:两个数列,每一次操作可以使一个 ai=max(ai−1,0)(1≤i≤n)。能否可以对 a进行若干次操作,使得a=b。
思路:首先某一个 bi>ai一定无解。因为ai只能减;然后,对 b 中的每一个数分类讨论:1.bi=0,此时 ans应满足 ans≥ai。2.bi≠0,此时 ans应满足 ans=ai−bi。判断是否存在一个 ans满足条件(ans就是任取两个数能得到的最大差值)。
#include<bits/stdc++.h> using namespace std; #define int long long void solve(){ int n,a[50001],b[50001]; cin>>n; for(int i=1;i<=n;i++){ cin>>a[i]; } int maxn=-2e9+100; for(int i=1;i<=n;i++){ cin>>b[i]; if(b[i]!=0) maxn=max(maxn,a[i]-b[i]); } if(maxn==-2e9+100){ cout<<"YES\n"; return; } bool flag=1; int dis=maxn; for(int i=1;i<=n;i++){ if(a[i]<b[i]) flag=0; if(b[i]==0&&a[i]-dis<=0){ continue; } if(a[i]-b[i]!=dis) flag=0; } if(flag) cout<<"YES\n"; else cout<<"NO\n"; } signed main() { ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); int t;cin>>t; while(t--){ solve(); } return 0; } G.Black and White Stripe
题意:修改最少次数使其正好出现长度为k且全是B的字符串。
思路:前缀和统计W的数量;然后从k到n遍历每一段长度为k的部分需要修改的次数与当前最小值比较。
#include<bits/stdc++.h> using namespace std; void solve(){ string s;int n,k; cin>>n>>k>>s; vector<int>w(n+1); for(int i=1;i<=n;i++) w[i]=w[i-1]+int(s[i-1]=='W'); int result=INT_MAX; for (int i=k;i<=n;i++) result=min(result,w[i]-w[i-k]); cout<<result<<endl; } signed main() { ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); int t;cin>>t; while(t--){ solve(); } return 0; }3.总结
- 不管是否输入数据都要数组初始化
- vector的使用不熟练导致不敢用
- 做题前需要有数学分析

浙公网安备 33010602011771号