2025 1.18-1.26 week 1

1.18-1.26 week 1

  1. 前言

  2. 补题

    1. SMU Winter 2025 Round 1
    2. SMU Winter 2025 Round 2
    3. SMU Winter 2025 Round 3
  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,这样他们的平均数就是21与3异或为2n-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的使用不熟练导致不敢用
    • 做题前需要有数学分析
posted @ 2025-01-26 23:04  kktwistz  阅读(57)  评论(0)    收藏  举报
一飞冲天按钮^^