Codeforces Round #637 (Div. 2)

A 已知有n個數,他們的範圍是[a-b,a+b],問這n個數(可以相等)的和是否能在[c-d,c+d]的範圍內,直接判斷即可。

#include<bits/stdc++.h>
using namespace std;
const int N=200010;
int t,n,m;
int main()
{
	cin>>t;
	while(t--)
	{
		int a,b,c,d;
		cin>>n>>a>>b>>c>>d;
		if((a+b)*n<(c-d)||(a-b)*n>(c+d)) puts("No");
		else puts("Yes");
	}
	return 0;
}

B 已知一個數組,如果a[i]>a[i-1]並且ai>a[i+1]那麼ai就是一個山峯,如果在區間l[l,l+k-1]內有m個山峯,那麼你的某種物品就被分成m+1份了,輸出最大的m+1和區間起點l,如果有多個輸出最小的l。預處理一下前面有多少個山峯,sum[i]就是前i個數的山峯數量(包括第i個數),這樣區間內的山峯數量就可以計算了。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=200010;
int t,n,m;
int a[N],sum[N];
int main()
{
	cin>>t;
	while(t--)
	{
		cin>>n>>m;
		for(int i=1;i<=n;i++) cin>>a[i];
		int k=0,l=1;
		for(int i=2;i<=n;i++)
		{
			if(a[i]>a[i-1]&&a[i]>a[i+1]&&i<n) sum[i]=sum[i-2]+1;
			else sum[i]=sum[i-1];
			if(i>=m&&sum[i-1]-sum[i-m+1]+1>k)
			{
				l=i-m+1;
				k=sum[i-1]-sum[i-m+1]+1;
			}
		}
		cout<<k<<' '<<l<<endl;
	}
	return 0;
}

C 題意比較繞,讀懂了就好理解了,按照題面意思生成隨機數組,生成規則是:
第i步爲數字i選擇一個位置,選擇依據是對於任意數字j(1<=j<=n)從第j個位置向後尋找第一個沒有被佔據的位置記爲r[j],沒有找到的不用管,最後統計所有數t(1<=t<=n)在r[]內出現的次數記爲count[t],選擇count[t]最大的數字t就是數字i的位置(如果有多個任意一個都可以)。

思路:假設n=7,i=1的時候count數組全爲0,隨意第一個,位置都可以任意選;假設選擇5,接下來給2選位置,r數組: 1 2 3 4 6 6 7(第5個位置後第一個沒被選的位置是6)count數組:1 1 1 1 0 2 1這時候只能選位置6;
然後選3的位置 r數組:1 2 3 4 7 7 7 ,count數組就是1 1 1 1 0 0 3,這時候就只能選位置7,
再給4選位置,r數組1 2 3 4 * * * (*)表示沒找到rj,count數組:1 1 1 1 0 0 0 ,
這時候位置1到4都可以選,看第一步是不是很類似,令n=4就一模一樣了;

對於n個數來說,1的位置可以任意選,假設選擇t[1],選2的位置的時候 r數組除了t[1]的所有位置i都是i(r[i]=i,i!=t[1]),只有t[1]例外r[t[1]=t[1]+1,所以count數組中只有count[t[1]+1]=2,其他都是1或者0(count[t[1]]=0),所以2只能選擇位置t[1]+1,3的位置也一樣只能選擇t[1]+2,所以t[1]往後都是遞增的且差值等1,直到位置n被選擇後,當前數可以選擇t[1]之前的數,這時令n=t[1]-1,就是回到第一步的時候了。

所以對於隨機數組ans,ans[i-1]<n的時候ans[i]必須等於ans[i-1]+1,當ans[i-1]==n時, 就可以選擇前面的任意數了,相當於將全面的區間劃分成連個,然後再後一個區間內一次遞增,直到完全選擇,然後再再前一個區間內劃分繼續一樣的操作直到1到n的數全部出現。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=200010;
int t,n,m;
int a[N],sum[N];
int main()
{
	cin>>t;
	while(t--)
	{
		cin>>n;
		for(int i=1;i<=n;i++) cin>>a[i];
		int l=1,r=n,k=-1;初始區間是[1,n],k=-1表示要選擇dl來劃分區間了
		bool flag=1;
		for(int i=1;i<=n;i++)//當時想的複雜了一些,代碼就繁瑣了
		{
			if(k==-1)//該劃分區間了
			{
				if(a[i]<l||a[i]>r)
				{
				 	flag=0;
				 	break;
				}
				else 
				{
					l=a[i];//這個時候就是dl
					if(l==r)//直接選擇了區間最後一個點
					{
						l=1;
						r--;
					}
					else
						k=a[i]-1;//k保存dl-1
				}
			}
			else 
			{
				if(a[i]!=l+1) //劃分過區間後就只能依次遞增了
				{
					flag=0;
					break;
				}
				else 
				{
					l=a[i];
					if(l==r) //[dl,r]內的被選完了就縮小區間唄
					{
						r=k;//k=dl-1
						l=1;//區間左端點會一直是1直到結束了
						k=-1;//該劃分區間了
					}
				}
			}
		}
		if(flag) puts("Yes");
		else puts("No");
	}
	return 0;
}

D待補,溜了溜了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章