Educational Codeforces Round 100 (Rated for Div. 2) 补题情况

战况(被hack掉一个 -2)

A. Dungeon

数学题,实际上一次抹掉三个同时,并且还能再抹掉6个所以一波就能干掉9个,至于他怎么干的完全可以不用去考虑,这里贪心即可。但是要注意看他干了几波,如果干的波数小于\(min(a,b,c)\)的话,那么肯定也是不行的。

所以首先判断\((a+b+c)\mod9 == 0?\) 如果可以再判断是否\(\frac{a+b+c}{9}\leq min(a,b,c)\) 即可

#include<bits/stdc++.h>
using namespace std;
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		long long a,b,c,d=INT_MAX;
		scanf("%lld%lld%lld",&a,&b,&c);
		long long s=a+b+c;
		if(s%9==0)
		{
			s/=9;
			if(s<=min(min(a,b),c)) puts("YES");
			else puts("NO");
		}
		else puts("NO");
	}
} 

B. Find The Array

构造题,两种做法。

第一种是直接构造所有的\(a[i]\)的同一位数的二进制数即可。这样能保证所有的整除关系。

例如\(a[i]=5\)那么\(5=(101)_2\) 我们构造\(b[i]=4=(100)_2\)这样我们的差值\(|a[i]-b[i]|=1=(001)_2\)可以证明这个插值一定是小于等于\(\lfloor\frac{a[i]}{2}\rfloor\)的。因为我之前的第一位已经占了一个一,我数向下取整除以二就是右移一位,并且我之前前面一定占有至少相同的一,所以相差不会大于要求。

#include <bits/stdc++.h>
using namespace std;
int a[1005];
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		int n;
		cin>>n;
		for(int i=1;i<=n;i++) cin>>a[i];
		int now=1;
		for(int i=1;i<=n;i++)
		{
			int now=1;
			while(1)
			{
				if(now*2>a[i]) 
				{
					cout<<now<<" ";
					break;
				}
				now*=2;
			}
		}
		cout<<"\n";
	}
}

第二种做法是,我们可以认为\(S=\sum_{i=1}^{n}a[i]=S_{odd}+S_{even}\)也就是说我们总和等于原数列的奇数项加上偶数项,我们看哪一项大就把\(b[i]\)对应的等于\(a[i]\)其他都设置成为1,这样的话\(2\sum_{i=1}^{n}|a[i]-b[i]|=2(a[1]+a[3]+...+a[n-1]-\frac{n}{2})=2S_{odd}-n\)(假设n是一个偶数,并且偶数项大于等于奇数项)​。因为\(S_{odd}\leq S_{even}\)所以\(2S_{odd}\leq S\),所以\(2S_{odd}-n\leq S\),所以这么分的话\(2\sum_{i=1}^{n}|a[i]-b[i]|\leq S\)满足题目要求。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a[105],s1,s2;
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		int n;
		s1=s2=0;
		scanf("%d",&n);
		for(int i=1;i<=n;i++) 
		{
			scanf("%lld",&a[i]);
			if(i&1) s1+=a[i];
			else s2+=a[i];
		}
		if(s1<=s2)
		{
			for(int i=1;i<=n;i++) if(i&1) printf("1 ");else printf("%lld ",a[i]);
		}
		else
		{
			for(int i=1;i<=n;i++) if(i&1) printf("%lld ",a[i]);else printf("1 ");
		}
		puts("");
	}
}

C. Busy Robot

直接模拟的题,按照题意模拟即可

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll t[100005],x[100005];
set<ll> st;
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		int n;
		scanf("%d",&n);
		for(int i=1;i<=n;i++) scanf("%lld%lld",&t[i],&x[i]); 
		t[n+1]=INT_MAX;
		t[n+1]+=t[n+1];
		ll tm=0,ans=0,pos=0,l=0,r=0,ltm=0,f=1,lpos=0;
		for(int i=1;i<=n;i++)
		{
			if(t[i]>=tm)  
			{
				ll d1=0;
				ll d2=d1+t[i+1]-t[i];
				if(x[i]>=pos)
				{
					f=1;
					l=pos+d1;
					r=pos+d2;
				}
				else
				{
					f=-1;
					r=pos-d1;
					l=pos-d2;
				}
				if(x[i]>=l&&x[i]<=r) ans++;
				ltm=t[i];
				tm=t[i]+llabs(pos-x[i]);
				lpos=pos;
				pos=x[i];
			}
			else
			{
				ll d1=t[i]-ltm;
				ll d2=min(tm,t[i+1])-ltm;
				if(f==1)
				{
					l=lpos+d1;
					r=lpos+d2;	
				}
				else
				{
					r=lpos-d1;
					l=lpos-d2;	
				}	
				if(x[i]>=l&&x[i]<=r) ans++;
			}	
		}
		printf("%lld\n",ans);
	}
} 

D. Pairs

给你\(2n\)个整数\(1,2,3,4,...,2n\)让你从中分出\(n\)个数对并且从中任意选出\(x\)个数对的最小值为\(b[i]\),从\(n-x\)个数对中选出最大值为\(b[i]\),且满足对于选出来的\(b[i]\)要等于\(a[i]\)并且\(a[i]\)为输入的数组,求\(0\leq x\leq n\)中有多少个\(x\)能够满足要求。

首先找出\(2n\)中剩下的数不在\(a[i]\)中的让他们组成\(c[i]\),然后把\(c[i]\)排序,顺便把\(a[i]\)也排序,因为我们任意选出数对来构造\(b[i]\)所以原来数组\(a[i]\)的顺序也无关紧要。如果我们要选择一个数对让他们的小的数成为\(b[i]\)那么我对应的这个位置上的\(a[i]\)必须得从\(c\)数组中有比我大的数才可以否则根本无法实现,反之亦然(vice versa)。于是我们就可以贪心的看看每个数到底有几个比他大的数在\(c\)数组中,有几个比他小的数。

这里还需要发现一个事,就是我如果给定的资源也就是数的个数是合适的话,我一定能够分配好,不管怎么分配。那么我只要确定好上下界限,也就是\(x\)的上下界限\(l,r\)即可,答案就是\(r-l+1\)因为我可以用的资源是够的,所以一定能够分配好。

但是我们怎么求的\(l,r\)呢?

实际上\(r\)就是最多的能有在\(c\)中比\(a[i]\)大的数的个数,这样就可以用小的数构造\(b[i]\)

\(l\)就是\(n-最多的能有在c中比a[i]小的数的个数\)因为这些数没有比他们小的,只能用大的数构造\(b[i]\)

所以现在问题就是找上面的什么比\(a[i]\)大比\(a[i]\)小的什么的个数了。

我们需要考虑一下这个数据

2

2 3

可以发现1不在\(a[i]\)中并且比2和3都要小,但是我这个1只能分配个一个,所以我需要从左到右的去寻找,来判断一下是否能够分配。

同样的4都比2 3大所以要从右到左的去寻找,来判断一下是否能够分配。

最终答案就是\(r-l+1\)时间复杂度为\(O(NlogN)\)

#include <bits/stdc++.h>
using namespace std;
int mk[500005],a[500005],b[500005],maxn[500005],minn[500005],n;
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		int p=0,m1,m2,x=0,y=0,ans=0;
		scanf("%d",&n);
		for(int i=1;i<=2*n;i++) mk[i]=0;
		for(int i=1;i<=n;i++) scanf("%d",&a[i]),mk[a[i]]++;
		for(int i=1;i<=2*n;i++) if(!mk[i]) b[++p]=i;
		sort(b+1,b+1+p);
		sort(a+1,a+1+n);
		for(int i=1;i<=n;i++)
		{
			m2=lower_bound(b+1,b+1+p,a[i])-b-1;
			if(m2>y) y++;
		}
		for(int i=n;i;i--)
		{
			m1=n-(upper_bound(b+1,b+1+p,a[i])-b)+1;
			if(m1>x) x++;
		}
		int l=n-y,r=x,L=l;
		printf("%d\n",r-l+1);
	}
}

小结

B不被hack就好了。。。A想的有点慢。

posted @ 2020-12-19 11:43  baccano!  阅读(209)  评论(0编辑  收藏  举报