Codeforces Round 486 (Div. 3)

目录

A. Diverse Team

B. Substrings Sort

C. Equal Sums

D. Points and Powers of Two

E. Divisibility by 25

F. Rain and Umbrellas


A. Diverse Team

 找出不重复的同时存下下标即可,依次遍历map判断重复最后判断数量即可

void solve(){
   
    cin>>n>>m;
    map<int,int> mp;
    vector<int> res;
    for(int i=1;i<=n;i++){
    	int x; cin>>x;
    	if(!mp.count(x))res.push_back(i);
    	mp[x]++;
    }
    if(res.size()<m) cout<<"NO"<<endl;
    else{
    	cout<<"YES"<<endl;
    	for(int i=0;i<m;i++) cout<<res[i]<<' ';
    	cout<<endl;
    }
    return ;
}

B. Substrings Sort

如果前一个是后一个的字串那么后一个的长度一定大于等于前一个,所以我没按照长度排序最后检查是不是满足都是字串即可

bool cmp(string a,string b){
	return a.size()<b.size();
}
void solve(){
    
    cin>>n;
    vector<string> s(n);
    for(auto&v:s) cin>>v;
    sort(s.begin(),s.end(),cmp);
    
    bool ok=true;
    for(int i=0;i<n;i++){
    	for(int j=i+1;j<n;j++){
    		if(s[j].find(s[i])==-1) ok=false;
    	}
    }
    if(!ok) cout<<"NO"<<endl;
    else{
    	cout<<"YES"<<endl;
    	for(auto&v:s) cout<<v<<endl;
    }
    return ;
}

C. Equal Sums

我没对删除每一个位置的数的结果记录起来用map记录前面的方案即可,为了防止自己这一排我没使用先遍历自己的答案最后把自己的加入即可

void solve(){
   
    cin>>n;
    bool ok=false;
    
    map<LL,PII> mp;
    for(int i=1;i<=n;i++){
    	cin>>m;
    	vector<int> a(m);
    	LL sum=0;
    	for(int j=0;j<m;j++){
    		cin>>a[j];
    		sum+=a[j];
    	}
    	if(ok) continue;
    	for(int j=0;j<m;j++){
    		if(mp.count(sum-a[j])){
    			ok=true;
    			cout<<"YES"<<endl;
    			auto [pos,id]=mp[sum-a[j]];
    			cout<<pos<<' '<<id<<endl;
    			cout<<i<<' '<<j+1<<endl;
    			break;
    		}
    	}
    	for(int j=0;j<m;j++){
    		mp[sum-a[j]]={i,j+1};
    	}
    }
    if(!ok) cout<<"NO"<<endl;
    return ;
}

D. Points and Powers of Two

我没研究性质可以发现其实最多只有三个不同的数出现因为如果还有更多的数的话一定不会是2的次方我们考虑三个数x-2^d,x,x+2^d,如果再加入一个数明显不成立所以最多三种我们不妨考虑枚举中间位置的数,然后枚举二进制即可

void solve(){
   
    cin>>n;
    map<int,int> mp;
    for(int i=0;i<n;i++){
    	int x; cin>>x;
    	mp[x]++;
    }
    int ans=0,id,pw;
    for(auto&[v,w]:mp){
    	for(int j=1,cnt=1;cnt<=31;cnt++,j*=2){
    		int now=w;
    		if(mp.count(v-j)) now+=mp[v-j];
    		if(mp.count(v+j)) now+=mp[v+j];
    		if(now>ans){
    			ans=now;
    			id=v,pw=j;
    		}
    	}
    }
    cout<<ans<<endl;
    while(mp.count(id) && mp[id]--) cout<<id<<' ';
    while(mp.count(id+pw) && mp[id+pw]--) cout<<id+pw<<' ';
    while(mp.count(id-pw) && mp[id-pw]--) cout<<id-pw<<' ';
    return ;
}

E. Divisibility by 25

25的倍数一定是25,50,75,00作为结尾,我们考虑依次移动到后面即可,接着发现可能会出现00的情况我们假设最后是00375我们可以把3移动到最前面即可所以加入一个特判即可

int ans=1e9;
void check(char a,char b){
	string ss(s);
	reverse(ss.begin(),ss.end());
	int cnt=0;
	for(int i=0;i<ss.size();i++){
		if(ss[i]==b){
			cnt+=i;
			
			for(int j=i;j>0;j--){
				swap(ss[j],ss[j-1]);
			}
			break;
		}
	}
	for(int i=1;i<ss.size();i++){
		if(ss[i]==a){
			cnt+=i-1;
			for(int j=i;j>1;j--){
				swap(ss[j],ss[j-1]);
			}
			break;
		}
	}
	reverse(ss.begin(),ss.end());
	bool ok=false;
	for(int i=0;i<ss.size();i++){
		if(ss[i]!='0'){
			ok=true;
			cnt+=i;
			break;
		}
	}
	if(!ok) cnt=1e9;
	ans=min(ans,cnt);
}
void solve(){
   
    cin>>s;
    vector<int> cnt(10);
    for(auto&v:s) cnt[v-'0']++;
    
    if(cnt[2]>=1 && cnt[5]>=1) check('2','5');
	
    if(cnt[5]>=1 && cnt[0]>=1) check('5','0');
   
    if(cnt[7]>=1 && cnt[5]>=1) check('7','5');
  
    if(cnt[0]>=2) check('0','0');
    cout<<(ans==1e9 ? -1 : ans)<<endl;
    return ;        
}

F. Rain and Umbrellas

我们明显的可以考虑到dp,有些时候我们可以简单的思考问题我的上一个状态是前面的所有状态还是可以简化位就上一个位置的状态这里明显可以这样来思考这个问题,我们必须要从合法的状态转移过来,也就是我在第i个点手上拿着第几个伞,第0个表示没有伞,然后判断我上一个位置有没有伞我这个位置有没有雨来转移

int dp[M][M];// 表示到第i个点时用的是第j个位置的雨伞// 0 表示现在没有伞
int cho[M];
int w[M];
int rain[M];
int S;
 
void solve()
{
	cin>>S>>n>>m;
	
	for(int i=1;i<=n;i++){
		int l,r; cin>>l>>r;
		for(int j=l+1;j<=r;j++)
			rain[j]=1;// 表示这个位置在下雨
	}	 
	w[0]=INF;
	
	for(int i=1;i<=m;i++){
		int v; cin>>v>>w[i];
		if(w[i]<=w[cho[v]]) cho[v]=i;
	}// 表示记录下来每一个位置的雨伞的权重,以及每一个雨伞在什么位置
	
	memset(dp,0x3f,sizeof dp);
	
	dp[0][0]=0;
	
	for(int i=1;i<=S;i++){
		for(int j=0;j<=m;j++){
			if(!rain[i]){// 如果我这个位置没有雨直接扔掉伞
				dp[i][0]=min(dp[i][0],dp[i-1][j]);
			}
			// 表示我接着用上一个位置的伞
			dp[i][j]=min(dp[i][j],dp[i-1][j]+w[j]);
			if (cho[i-1]){// 对于这个位置的上一个位置有伞换一手
                dp[i][cho[i-1]]=min(dp[i][cho[i-1]],dp[i-1][j]+w[cho[i-1]]);
            }
		}
	}
	
	int ans=INF;
	
	for(int i=0;i<=m;i++) ans=min(ans,dp[S][i]);
	
	cout<<(ans==INF ? -1 : ans)<<endl;
    return ;
}

  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值