Codeforces Round #773 (Div. 2)

A. Hard Way

题目大意:给你一个位于第一象限的三角形,问不能由x轴上的点沿直线达到的线段长度。
首先要满足题意三角形一定得是个倒三角形,而且最上面的边必须平行与x轴,这样只需要输出这条边的长度即可。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<algorithm>
#include<map>
#include<cmath>
#include<queue>
#define clean(x) memset(x,0,sizeof(x))
#define maxn 1000005
using namespace std;

int read()
{
	int x=1,res=0;
	char c=getchar();
	while(c<'0'||c>'9')
	{
		if(c=='-')
		x=-1;
		c=getchar();
	}
	while(c>='0'&&c<='9')
	{
		res=res*10+(c-'0');
		c=getchar();
	}
	return res*x;
}
struct node{
	double x,y;
}g[maxn];
bool cmp(node a,node b)
{
	return a.y>b.y;
}
void solve()
{
	double x[4],y[4];
	cin>>g[1].x>>g[1].y>>g[2].x>>g[2].y>>g[3].x>>g[3].y;
	sort(g+1,g+1+3,cmp);
	if(g[1].y==g[2].y){
		printf("%.9lf\n",abs(g[1].x-g[2].x));
	}
	else puts("0");
}
int main()
{
	int t=read();
	while(t--)
	solve();
}

B. Power Walking

题目大意:给你一个序列,然后分别将其分成1~n份,问每一次分后,求每一份中不同数的个数的和最小是多少。
我们要使得每一份中不同的数的个数尽量小,那么每一份中就要尽可能多的含有相同的数,因此,我们统计序列中不同的数的个数,记为cnt,那么当分成的份数小于等于cnt时,答案就是cnt,我们只需要将相等的数分在同一份中即可,而份数大于cnt时,答案就等于分的份数。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<algorithm>
#include<map>
#include<cmath>
#include<queue>
#define clean(x) memset(x,0,sizeof(x))
#define maxn 1000005
using namespace std;

int read()
{
	int x=1,res=0;
	char c=getchar();
	while(c<'0'||c>'9')
	{
		if(c=='-')
		x=-1;
		c=getchar();
	}
	while(c>='0'&&c<='9')
	{
		res=res*10+(c-'0');
		c=getchar();
	}
	return res*x;
}
int cnt[maxn],a[maxn],b[maxn],f[maxn];
void solve()
{
	int n=read();
	for(int i=1;i<=n;i++){
		cnt[i]=0;
		f[i]=0;
	}
	for(int i=1;i<=n;i++) a[i]=read(),b[i]=a[i];
	sort(a+1,a+1+n);
	int tott=unique(a+1,a+1+n)-a-1;
	for(int i=1;i<=n;i++)
	{
		if(i<=tott)
		printf("%d ",tott);
		else printf("%d ",i);
	}puts("");
}
int main()
{
	int t=read();
	while(t--)
	solve();
}

C.Great Sequence

题目大意:给你一个序列和一个数x,每次操作可向序列中添加任何数,要求将序列中的数两两配对且商为x,求最小操作次数。
我们可以从小到大依次寻找匹配对象,如果某个数乘以x在序列中出现,那么这两个数就可以直接配对,否则我们就需要额外添加一个数进行配对。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<algorithm>
#include<map>
#include<cmath>
#include<queue>
#define int long long
#define clean(x) memset(x,0,sizeof(x))
#define maxn 1000005
using namespace std;

int read()
{
	int x=1,res=0;
	char c=getchar();
	while(c<'0'||c>'9')
	{
		if(c=='-')
		x=-1;
		c=getchar();
	}
	while(c>='0'&&c<='9')
	{
		res=res*10+(c-'0');
		c=getchar();
	}
	return res*x;
}
map<int,int>s;
int a[maxn];
void solve()
{
	int n=read(),x=read(),ans=0,aa;
	s.clear();
	for(int i=1;i<=n;i++) {
		a[i]=read();
		s[a[i]]++;
	}
	sort(a+1,a+1+n);
	for(int i=1;i<=n;i++)
	{
		if(!s[a[i]]) continue;
		if(s[a[i]]&&s[a[i]*x]){
			s[a[i]]--;
			s[a[i]*x]--;
		}
		else {
			s[a[i]]--;ans++;
		}
	}
	printf("%d\n",ans);
}
signed main()
{
	int t=read();
	while(t--)
	solve();
}

D. Repetitions Decoding

题目大意:每次向序列中连续添加两个相同的元素且两个元素相邻,构造一种添加方案使得序列可以被拆分为多个AA型子序列。
首先每次只能添加两个元素,且两个元素相同,那么如果某个数只出现一次,一定无解。其次我们想要构造合法方案,首先需要找到两个相同的数,我们可以选取序列的第一个元素位置记为 l l l,然后找到下一个和第一个数相同的数这个位置记为 r r r,然后我们就可以依次添加区间 ( l , r ) (l,r) (l,r)中的数以此来形成一个AA型序列,比如说ABCDA就可以依次添加BB,CC,DD来构造形成ABCD ABCD DCB这样就可以成功消去两个A个元素,而且每次只需要操作小于n次,这样就可以保证在 O ( n 2 ) O(n^2) O(n2)时间复杂度内得出结果,具体实现过程可以使用vector,细节比较多,可能不是很好调。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<algorithm>
#include<map>
#include<cmath>
#include<queue>
#define clean(x) memset(x,0,sizeof(x))
#define maxn 1000005
using namespace std;

int read()
{
	int x=1,res=0;
	char c=getchar();
	while(c<'0'||c>'9')
	{
		if(c=='-')
		x=-1;
		c=getchar();
	}
	while(c>='0'&&c<='9')
	{
		res=res*10+(c-'0');
		c=getchar();
	}
	return res*x;
}
struct node{
	int x,y;
}g[maxn];
int a[maxn],nt[maxn],f[maxn],tot1,tot2;
vector<int>s;
void solve()
{
	tot1=tot2=0;
	int n=read(),pd=0,cnt=0,ans,now=0,tot=n-1;
	s.clear();
	for(int i=1;i<=n;i++)
	{
		a[i]=read();
		s.push_back(a[i]);
	}
	for(int i=1;i<=n;i++) nt[i]=0;
	for(int i=1;i<=n;i++){
		if(nt[i]==-1) continue;
		for(int j=i+1;j<=n;j++)
		{
			if(nt[j]==-1) continue;
			if(a[j]==a[i]) {
				nt[i]=j;
				nt[j]=-1;
				break;
			}
		}
	}
	for(int i=1;i<=n;i++) if(nt[i]==0) pd=1;
	if(pd) {puts("-1");return;}
	while(now<=tot){
		int x=s[now];
		for(int i=now+1;now<=tot;i++){
			if(x==s[i]){
				for(int j=now+1;j<i;j++){
					s.insert(s.begin()+i+j-now,s[j]);
					s.insert(s.begin()+i+j-now,s[j]);
					g[++tot2]=(node){i+j-now,s[j]};
					tot+=2;
				}
				f[++tot1]=(i-now)*2;
				now=(i-now)*2+now;				
				break;
			}
		}
	}
	printf("%d\n",tot2);
	for(int i=1;i<=tot2;i++)
	printf("%d %d\n",g[i].x,g[i].y);
	printf("%d\n",tot1);
	for(int i=1;i<=tot1;i++)
	printf("%d ",f[i]);
	puts("");
}

int main()
{
	int t=read();
	while(t--)
	solve();
	return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

snowy2002

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值