2019.8.17Codeforces Round #579 (Div. 3)补题

这次div3打的有点菜啊

题目

官方题解
又开始了自闭后的补题,这次不把题面复制过来了,我感觉都不会看的,想看就去原网站吧[可怜][委屈][要哭了]

A.Circle of Students

题意

小朋友们是否依次连成了顺/逆的环

思路

硬写

AC的代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int inf=0x3f3f3f3f;
int a[205];
int jud(int n,int x)
{
	if(n==1)
		return 1;
	for(int i=1;i<n;i++)
		if(a[(x+i)%n]!=i)
			break;
		else if(i==n-1)
			return 1;
	for(int i=1;i<=n;i++)
		if(a[(n+x-i)%n]!=i)
			break;
		else if(i==n-1)
			return 1;
	return 0;
}
int main()
{
	int t,n,loc;
	cin>>t;
	while(t--){
		cin>>n;
		for(int i=0;i<n;i++){
			scanf("%d",&a[i]);
			if(a[i]==1)
				loc=i;
			a[i]--;
		}
		if(jud(n,loc))
			cout<<"YES"<<endl;
		else
			cout<<"NO"<<endl;
	}
	return 0;
}

B. Equal Rectangles

题意

给你4n个木棒,能否构建n个面积相等的矩形。

思路

硬算

AC的代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int inf=0x3f3f3f3f;
int a[405];
int main()
{
	int t,n;
	cin>>t;
	while(t--){
		cin>>n;
		for(int i=0;i<4*n;i++)
			scanf("%d",&a[i]);
		sort(a,a+4*n);
		int squ=a[0]*a[4*n-1];
		int i=0,j=4*n-1,flag=1;
		while(i<j)
		{
			if(a[i]!=a[i+1]||a[j]!=a[j-1]){
				flag=0;
				break;
			}
			if(a[i]*a[j]!=squ){
				flag=0;
				break;
			}
			i+=2;
			j-=2;
		}
		if(flag)
			cout<<"YES"<<endl;
		else
			cout<<"NO"<<endl;
	}
	return 0;
}

C. Common Divisors

题意

给你n个数,求出能整除所有这n个数的数的个数。

思路

求出这n个数的最大公因数,在求出这个公因数的所有因数。
我比赛时就这么写的啊,为什么就T了呢[快哭了]

AC的代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int inf=0x3f3f3f3f;
int main()
{
	long long n,temp;
	int i,j;
	while(cin>>n){
		cin>>temp;
		long long g=temp;
		for(i=1;i<n;i++)
		{
			scanf("%I64d",&temp);
			g=__gcd(g,temp);
		}
		int cnt=0;
		for(long long i=1;i*i<=g;i++)
		{
			if(g%i==0){
				cnt++;
				if(i!=g/i)
				cnt++;
			}
		}
		cout<<cnt<<endl;
	}
	return 0;
}

D1. Remove the Substring (easy version)&&D2. Remove the Substring (hard version)

题意

给你字符串s和t,从s中移除尽量多的字符,保证t是s的子串。输出移除的最大连续串长度。

思路

上次div3D题就是字符串,又见字符串。
看到题解时一脸懵逼,看懂题解后大喊666

AC的代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int inf=0x3f3f3f3f;
char s[200005],t[200005];
int rg[200005];//记录t[i]尽量向s末尾靠对应字符s[rg[i]]
int main()
{
	cin>>s>>t;
	int i,j,slen=strlen(s),tlen=strlen(t);
	for(i=tlen-1;i>=0;i--)//预处理rg数组
	{
		int pos=slen-1;//指向s末尾
		if(i+1<tlen)//正在检查的不是倒数第一个
			pos=rg[i+1]-1;//从t[i+1]对应的rg[i+1]-1开始寻找
		while(s[pos]!=t[i])
			pos--;
		rg[i]=pos;
	}
	int ans=0,pos=0;
	for(i=0;i<slen;i++)//从前向后遍历s
	{
		int rpos=slen-1;//如果pos==tlen,则可以直接从s末尾删到rg[tlen]+1
		if(pos<tlen)//pos记录当前匹配到t[pos]
			rpos=rg[pos]-1;//:可删除字符串右端,t[pos]在s中对应最右位置
		ans=max(ans,rpos-i+1);
		if(pos>=tlen)
			break;
		if(pos<tlen&&t[pos]==s[i])//t[pos]匹配到了可行字符
			pos++;//t[pos]段的可删除字符串不会再有更长的了,匹配下一个t[pos]
	}
	cout<<ans<<endl;
	return 0;
}


E . Boxers

题意

给你n个数,每个数可以+1或-1或不变,问你最后最多有多少种数。

思路

胡搞

AC的代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define PI 3.14159265358979323846
#define e  2.7182818284590452354
#define ln_2 0.69314718055994530942
#define ln_10 2.30258509299404568402
using namespace std;
const int inf=0x3f3f3f3f;
int a[150010];
int main()
{
	int n,maxn=0,i,j,temp;
	cin>>n;
	while(n--){
		scanf("%d",&temp);
		a[temp]++;
		maxn=max(maxn,temp);
	}
	for(i=1;i<=maxn;i++)
	{
		if(a[i]==0&&a[i+1]>0)
		{
			a[i]++;
			a[i+1]--;
		}
	}
	for(i=maxn+1;i>=0;i--)
	{
		if(a[i]==0&&a[i-1]>0)
		{
			a[i]++;
			a[i-1]--;
		}
	}
	int cnt=0;
	for(i=1;i<=maxn+5;i++)
		if(a[i]>0)
			cnt++;
	cout<<cnt<<endl;
	return 0;
}

F1. Complete the Projects (easy version)

题意

初始等级为r,有n个任务,第i个任务需要等级>=ai才可以做,做完后等级变化bi。等级必须在任何时刻都>=0,问你有没有可能完成所有任务。

思路

将任务分成b>=0和b<0两组,b>=0组按所需等级从小到大排序。b<0组按a+b从大到小排序,因为每个任务都要做,做完这个任务之后的最低分数为a+b。

AC的代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
using namespace std;
#define PI 3.14159265358979323846
#define e  2.7182818284590452354
#define ln_2 0.69314718055994530942
#define ln_10 2.30258509299404568402
const int inf=0x3f3f3f3f;
struct node
{
	int a,b;//需要等级,等级变化
};
struct cmp
{
	bool operator() (node x,node y)
	{
		return x.a>y.a;//把需要等级小的放在堆顶
	}
};
struct cmp2//neg数组
{
	bool operator() (node x,node y)
	{
		return x.a+x.b<y.a+y.b;//做完这个任务的最低分数[a+b,+∞)
        //因为每个任务都要做,所以我们按a+b从大到小排序即可
	}
};
int main()
{
	int n,r,i,j,flag=1;//保证等级始终>0&&>a[i]
	node tem;
	cin>>n>>r;
	priority_queue<node,vector<node>,cmp>pos;
	priority_queue<node,vector<node>,cmp2>neg;
	for(i=0;i<n;i++)
	{
		scanf("%d%d",&tem.a,&tem.b);
		if(tem.b>=0)
			pos.push(tem);
		else
			neg.push(tem);
	}
	while(!pos.empty())
	{
		tem=pos.top();
		pos.pop();
//		printf("1.a=%d,b=%d,r=%d\n",tem.a,tem.b,r);
		if(r<tem.a)
		{
			flag=0;
			goto label;
		}
		r+=tem.b;
	}
	while(!neg.empty())
	{
		tem=neg.top();
		neg.pop();
//		printf("2.a=%d,b=%d,r=%d\n",tem.a,tem.b,r);
		if(r<tem.a)
		{
			flag=0;
			goto label;
		}
		r+=tem.b;
		if(r<0)
		{
			flag=0;
			goto label;
		}
	}
	label:
		cout<<(flag?"YES":"NO")<<endl;
	return 0;
}

F2 - Complete the Projects (hard version)

题意

大概内容同上,本题不必判断是否能完成所有任务,输出最多可以完成的任务。

思路

贪心+DP。还是分为pos和neg两组。
先贪心求出最多能取pos的数量,得到最大r。
再用DP求出最多可以取得的neg的数量。
啊啊啊,我DP还不是很熟,自己看完题解魔改总是WA。[委屈]

AC的代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<map>
using namespace std;
#define PI 3.14159265358979323846
#define e  2.7182818284590452354
#define ln_2 0.69314718055994530942
#define ln_10 2.30258509299404568402
const int inf=0x3f3f3f3f;
int dp[105][50005];//dp[i][j]表示第i个b<0的任务,当前r=j,值表示取到b<0最多的数量
bool cmp(const pair<int,int> a,const pair<int,int> b)
{
	return a.first + a.second > b.first + b.second;
}
int main()
{
	int n,r,i,j;
	cin>>n>>r;
	vector<pair<int,int> > pos,neg;
	for(i=0;i<n;i++)
	{
		pair<int,int> tem;
		cin>>tem.first>>tem.second;
		if(tem.second>=0)
			pos.push_back(tem);
		else{
			neg.push_back(tem);
		}
	}
	sort(pos.begin(),pos.end());
	sort(neg.begin(),neg.end(),cmp);
	int cnt=0;
	for(i=0;i<pos.size();i++)
	{
		if(r>=pos[i].first)
		{
			r+=pos[i].second;
			cnt++;
		}
		else
			break;
	}
	memset(dp,0,sizeof(dp));
	for(i=0;i<int(neg.size());i++)//第i项任务
	{
		for(j=0;j<=r;j++)//j为当前的等级
		{
			if(j>=neg[i].first&&j+neg[i].second>=0)//i合法,可以做
			{//更新做完i的状态
				dp[i+1][j+neg[i].second]=max(dp[i+1][j+neg[i].second],dp[i][j]+1);
			}
			dp[i+1][j]=max(dp[i+1][j],dp[i][j]);
		}
	}
	int maxneg=0;
	for(i=0;i<=r;i++)
		maxneg=max(maxneg,dp[int(neg.size())][i]);
	cout<<cnt+maxneg<<endl;
	return 0;
}

2019年8月19日21点50分

发布了71 篇原创文章 · 获赞 12 · 访问量 7548

猜你喜欢

转载自blog.csdn.net/Miaplacidus/article/details/99698492