• Codeforces Round #543 (Div. 2) D 双指针 + 模拟


    https://codeforces.com/contest/1121/problem/D

    题意

    给你一个m(<=5e5)个数的序列,选择删除某些数,使得剩下的数按每组k个数以此分成n组(n*k<=m),存在只要一组满足和目标集合s(|s|<=k)匹配(即集合中存在的数,组内一定存在)

    题解

    • 重点:找出至少一组满足要求的数
    • 假设[l,r]内满足要求,还需要满足:((l-1)/k*k+(m-r)/k*k>=k*(n-1)),可以用双指针,对于每个l可以处理出最小的r满足要求
    • 这样就把数组分成了三段[1,l-1],[l,r],[r+1,m],第一段[1,l-1]删除数字使得可以被k整除(没有限制随便删除),第二段[l,r]分成两种情况:
      1. (r-l+1)>k:去掉(r-l+1-k)个不符合要求的数
      2. (r-l+1)==k:不用删除任何数

    坑点

    • 对于第二段的第一种情况,不符合要求的数包括:
      1. 不在集合内的数
      2. 在集合内,但超出集合数量的数
      • 模拟时应该优先删除不在集合内的数,并统计数目,数目不够再删除在集合内的数,假如优先删除在集合内的数,有可能会导致[l,r]内不符合要求

    代码

    #include<bits/stdc++.h>
    #define M 500005
    using namespace std;
    int m,k,n,s,a[M],mp[M],x,kd,cnt,vi[M],l,r,ed,i,rm,CNT;
    map<int,int>mk;
    vector<int>ans;
    int main(){
    	cin>>m>>k>>n>>s;
    	for(i=1;i<=m;i++)scanf("%d",&a[i]);
    	for(i=1;i<=s;i++){
    		scanf("%d",&x);
    		if(!mp[x]){kd++;}
    		mp[x]++;
    	}
    	cnt=0;
    	for(l=1;l<=m;){
    		while(cnt<kd&&r<=m){
    			vi[a[++r]]++;
    			if(vi[a[r]]==mp[a[r]])cnt++;
    			//if(vi[r]==mp[x]+1)cnt--;
    		}
    		if(r>m)break;
    		if(cnt==kd){
    			ed=max(l+k-1,r);
    			if(ed<=m){
    				if((l-1)/k+(m-ed)/k>=n-1){
    					rm=(l-1)%k;
    					for(i=1;i<=rm;i++)ans.push_back(i);
    					mk.clear();
    					if(r>l+k-1){
    						CNT=r-(l+k-1);
    					for(i=l;i<=ed;i++){
    						if(mp[a[i]]&&mk[a[i]]<mp[a[i]]){
    							mk[a[i]]++;
    						}else if(CNT){
    							ans.push_back(i);
    							CNT--;
    						}
    					}
    					}					
    					printf("%d
    ",ans.size());
    					for(i=0;i<ans.size();i++)
    						printf("%d ",ans[i]);	
    					return 0;
    				}
    			}
    		}
    		if(vi[a[l]]==mp[a[l]])cnt--;
    		vi[a[l++]]--;
    	}
    	cout<<-1;
    }
    
  • 相关阅读:
    【Redis】搭建主从复制
    【安装】Ubuntu之Docker
    【安装】Ubuntu之MySQL
    【Docker】Dockerfile构建指令
    【Docker】常用命令
    【14】Flask 请求上下文
    【13】Flask 上下文前夕
    【12】Flask 分析线程和协程
    【11】Flask 高级进阶
    【10】Flask 高级摘要
  • 原文地址:https://www.cnblogs.com/VIrtu0s0/p/10486509.html
Copyright © 2020-2023  润新知