Codeforces Round 993 (Div. 4)D、E,G1题(G2有空补)

D

思路:直接按最简单的构造,让1-n的每个数都只出现一次,对于第一次出现的数字,那肯定是要先输出的,然后对于重复的输出这个数组中没有出现的数字,例如给你n=5   1 1 2 4 3,对于第二个因为1已经出现过,那么我们就直接拿1-n中数组没有出现的数字5去补,确保每个数字都只出现一次,那么每个数都是

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
unordered_map<int,int>mp;
vector<int>v1,v;
int t,n;
int a[200010]; 
int main()
{
	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	cin>>t;
	while(t--)
	{
		mp.clear();
		v1.clear();
		v.clear();
		cin>>n;
		for(int i=1;i<=n;i++) 
		{
	    	cin>>a[i];
	    	mp[a[i]]++; 
		} 
//用一个vector存储1-n中数组中没有出现的数字,那这个数字去补重复的
		for(int i=1;i<=n;i++)
		{
			if(!mp[i]){
				mp[i]++;
				v1.push_back(i);
				}
	    }
		mp.clear();
		int l=0;
		for(int j=1;j<=n;j++)
		{
			if(!mp[a[j]])
			{
				mp[a[j]]++;
				v.push_back(a[j]);
			}else{
				v.push_back(v1[l++]);
				}
		}
		for(int k=0;k<v.size();k++) cout<<v[k]<<' ';
		cout<<endl;
	}
    return 0;
}

E

思路:因为l1≤x≤r1l1≤x≤r1,l2≤y≤r2l2≤y≤r2.要满足y/x=k^{n},那么我们可以通过二分查找在l1-r1中满足x*k^{n}>=l2的最小x1,再二分查找<=r2的最小值x2,此时x2-x1+1就是满足的区间,因为只有1e9所以枚举到n=30即可。

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
int t,l1,r1,l2,r2,k,sum,res;
bool check1(int x)
{
	if(x*res>=l2) return true;
	else return false;
}
bool check2(int x)
{
	if(x*res<=r2) return true;
	else return false;
}
signed main()
{
	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	cin>>t;
	while(t--)
	{
		cin>>k>>l1>>r1>>l2>>r2;
		sum=0;
		for(int i=0;i<32;i++)
		{
			res=pow(k,i);
			if(res>r2) break;
			int l=l1-1,r=r1+1;
            //查找满足的最小值
		    while(l+1<r)
		    {
		    	int mid=(l+r)/2;
		    	if(check1(mid)) r=mid;
		    	else l=mid;
			}
			int ans1=r;
			l=l1-1,r=r1+1;
            //查找满足的最大值
		    while(l+1<r)
		    {
		    	int mid=(l+r)/2;
		    	if(check2(mid)) l=mid;
		    	else r=mid;
			}	
			int ans2=l;
			
			if(ans1*res>=l2&&ans2*res<=r2) sum+=ans2-ans1+1;
		}
		cout<<sum<<endl;
	}
    return 0;
}

G1

思路:对于简单版本,玩具不会超过1,先把数组中没有出现的数字存起来,因为下一年这些数字对应的下标就要为0,也就是说下一轮要存储的是上一轮不能收到玩具的ai,以此类推就行。

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
unordered_map<int,int>mp;
int a[200010],t,n,sum;
queue<int>q1,q2;
int main()
{
	cin>>t;
	while(t--)
	{
		mp.clear();
		cin>>n;
		sum=0;
		for(int i=1;i<=n;i++)
		{
			cin>>a[i];
			mp[a[i]]++;
		}
		for(int i=1;i<=n;i++)
		{
			if(!mp[i]) q1.push(i);
		}
		int flag1=0,flag2=0;
		while(q1.size()||q2.size())
		{
			while(q1.size())
			{
				int t=q1.front();
				q1.pop();
             //只有当i完全不能收到ai传来的玩具时,才能存起来,
				mp[a[t]]--;
				if(mp[a[t]]==0) q2.push(a[t]);
				flag1=1;
			}
			if(flag1==1)
			{
				flag1=0;
				sum+=1;
			}
			while(q2.size())
			{
				int t=q2.front();
				q2.pop();
				mp[a[t]]--;
				if(mp[a[t]]==0) q1.push(a[t]);
				flag2=1;
			}
			if(flag2==1)
			{
				flag2=0;
				sum+=1;
			}
		}
		cout<<sum+2<<endl;
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值