Codeforces Round #698 (Div. 2)

A

 

最长连续个数

 

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=105;
int n,a[maxn]; 
int main()
{
//	freopen("a.in","r",stdin);
//	freopen("a.out","w",stdout);
	int t;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&n);
		int ans=0;
		for(int i=1;i<=n;i++)
			scanf("%d",&a[i]);
		for(int i=1;i<=n;i++)
		{
			int cnt=1;
			while(a[i]==a[i+1] && i<n)
			{
				i++; cnt++;
			}
			ans=max(ans,cnt);
		}
		printf("%d\n",ans);
	}
	return 0;
}

 

B

 

这道题目还蛮有趣

就是当一个a>10*d 一定可以表示出来

简单证明如下:首先10*d-10*d+9 一定都可以表示出来,大于10*d+9的一定可以通过-d来达到这个区间

所以我们只需要暴力去进行计算a<10*d的数字了

 

这个想法我貌似在一道模拟题中也见过,数据范围很大,看起来并不像是可以暴力dfs的,但是可以证明大于十几的都不需要计算,最后复杂度就在O(2^n)

 

代码

#include<bits/stdc++.h>
using namespace std;
int main()
{
//	freopen("a.in","r",stdin);
//	freopen("a.out","w",stdout);
	int t;
	scanf("%d",&t);
	while(t--)
	{
		int q,d,x;
		scanf("%d%d",&q,&d);
		for(int i=1;i<=q;i++)
		{
			scanf("%d",&x);
			if(x>=d*10) printf("YES\n");
			else
			{
				int sum=0,ok=0;
				for(int i=1;i<10;i++)
					if((i*d)%10==x%10 && i*d<=x) ok=1;
				if(!ok) printf("NO\n");
				else printf("YES\n");
			}
		}
	}
	return 0;
}

 

C

 

这道题目只需要手动模拟几组就可以很轻松的得到公式了,要注意先不妨设一下相对大小来避免绝对值的讨论,然后呢,就是通过一对一对从大到小的计算,注意要验证算出来的数的确是递增的才可以!

 

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+5;
ll a[maxn],b[maxn];
int n;
bool cmp(ll x,ll y)
{
	return x>y;
}
int main()
{
//	freopen("a.in","r",stdin);
//	freopen("a.out","w",stdout);
	int t;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&n);
		for(int i=1;i<=2*n;i++) scanf("%lld",&a[i]);
		sort(a+1,a+2*n+1,cmp);
		int j=1,ok=0;
		ll sum=0,last=0,now=0;
		for(int i=n;i>=1;i--)
		{
			if(a[j]!=a[j+1] || (a[j]-last)%(1LL*i*2)!=0)
			{
				ok=1;
				break;
			}
			now=(a[j]-last)/(1LL*i*2);
			b[i]=now;
			last+=2*now;
			j+=2;
		}
		for(int i=1;i<=n;i++) if(b[i]<=b[i-1]) ok=1;
		if(!ok) printf("YES\n");
		else printf("NO\n");
	}
	return 0;
}

 

D

 

题意:给出一个序列,你可以任意挑选两个数x,y将2*x-y加入序列中,询问在是否可以在序列中得到k
 

首先可以把2*x-y看成x+(x-y)这也就是每个数加上它与另外一个数的差,所以我们只需要考虑能否将ai通过加上差值得到k

由于a3-a1这种的可以转换为a3-a2+a2-a1,所以我们需要考虑的只有相邻两个数的差值,然后由于n个数之间的裴蜀定理,就可以证明出来,只需要证明(k-a[1])% gcd(delta(ai+1-ai) =0 即可

 

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+5;
int n;
ll k,a[maxn],d[maxn]; 
ll gcd(ll x,ll y)
{
	return (!y)?x:gcd(y,x%y);
}
int main()
{
//	freopen("a.in","r",stdin);
//	freopen("a.out","w",stdout);
	int t;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%lld",&n,&k);
		for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
		sort(a+1,a+n+1);
		for(int i=1;i<n;i++) d[i]=a[i+1]-a[i];
		ll g=d[1];
		for(int i=2;i<n;i++) g=gcd(g,d[i]);
		if((k-a[1])%g==0) printf("YES\n");
		else printf("NO\n");
	}
	return 0;
}

 

E

 

发现按时间逆序之后,每次修改后要保证这个区间同色。

因为一次只能修改小于 len/2个数字,所以一定是修改成数量比较多的那种数字,所以直接用线段树打区间覆盖维护区间和就行了。

特别地,区间查询发现如果 01 数量相同则输出 NO,如果最终状态不符合初始状态也是 NO。

 

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+5;
int n,m;
int s[maxn],f[maxn],xx[maxn],yy[maxn];
struct tree
{
	int l,r,sum,lz;
}tr[maxn<<2];
void pushup(int now)
{
	tr[now].sum=tr[now<<1].sum+tr[now<<1|1].sum;
}
void pushdown(int now)
{
	if(tr[now].lz==-1) return;
	int v=tr[now].lz;
	tr[now<<1].lz=v; tr[now<<1|1].lz=v;
	tr[now<<1].sum=(tr[now<<1].r-tr[now].l+1)*v;
	tr[now<<1|1].sum=(tr[now<<1|1].r-tr[now<<1|1].l+1)*v;
	tr[now].lz=-1;
}
void build(int now,int l,int r)
{
	tr[now]=(tree){l,r,0,-1};
	if(l==r)
	{
		tr[now].sum=f[l];
		return;
	}
	int mid=l+r>>1;
	build(now<<1,l,mid);
	build(now<<1|1,mid+1,r);
	pushup(now);
}
int query(int now,int l,int r)
{
	if(tr[now].l>=l && tr[now].r<=r) return tr[now].sum;
	pushdown(now);
	int mid=tr[now].l+tr[now].r>>1;
	int res=0;
	if(l<=mid) res+=query(now<<1,l,r);
	if(mid<r) res+=query(now<<1|1,l,r);
	return res;
}
void update(int now,int l,int r,int v)
{
	if(l<=tr[now].l && tr[now].r<=r)
	{
		tr[now].lz=v;
		tr[now].sum=(tr[now].r-tr[now].l+1)*tr[now].lz;
		return;
	}
	pushdown(now);
	int mid=tr[now].r+tr[now].l>>1;
	if(l<=mid) update(now<<1,l,r,v);
	if(mid<r) update(now<<1|1,l,r,v);
	pushup(now);
}
int main()
{
//	freopen("a.in","r",stdin);
//	freopen("a.out","w",stdout);
	int t;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;i++) scanf("%1d",&s[i]);
		for(int i=1;i<=n;i++) scanf("%1d",&f[i]);
		for(int i=1;i<=m;i++) scanf("%d%d",&xx[i],&yy[i]);
		build(1,1,n);
		int flag=0;
		for(int i=m;i>=1;i--)
		{
			int l=xx[i],r=yy[i];
			int len=r-l>>1;
			int one=query(1,l,r);
			int zero=r-l+1-one;
			if(zero<=len) update(1,l,r,1);
			else if(one<=len) update(1,l,r,0);
			else
			{
				flag=1;
				break;
			}
		}
		if(flag)
		{
			printf("NO\n");
			continue;
		}
		for(int i=1;i<=n;i++)
			if(s[i]!=query(1,i,i))
			{
				flag=1;
				break;
			}
		if(flag) printf("NO\n");
		else printf("YES\n");
	}
	return 0;
}

 

F

贪心的考虑每次取最远的,看是否满足即可

 

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=5005;
int n;
ll x[maxn],y[maxn];
int ans[maxn],vis[maxn];
ll calc_dis(int a,int b)
{
	return (x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b]);
}
ll calc_dot(ll a,ll b,ll c,ll d)
{
    return a*c+b*d;
}
int judge(int a,int b,int c)
{
	if(calc_dot(x[b]-x[a],y[b]-y[a],x[b]-x[c],y[b]-y[c])<0)
		return 1;
	return 0;
}
int main()
{
//	freopen("a.in","r",stdin);
//	freopen("a.out","w",stdout);
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%lld%lld",&x[i],&y[i]);
	int x1=x[1],y1=y[1],last=1;
	vis[1]=1; ans[1]=1;
	for(int i=2;i<=n;i++)
	{
		ll dis=0,point=-1; 
		for(int j=2;j<=n;j++)
		{
			if(vis[j]) continue;
			if(dis<calc_dis(last,j))
			{
				dis=calc_dis(last,j);
				point=j;
			}
		}
		if(i>=3 && judge(ans[i-2],ans[i-1],point)==1)
		{
			printf("-1\n");
			return 0;
		}
		last=point;
		vis[point]=1;
		ans[i]=point;
	}
	for(int i=1;i<=n;i++) printf("%d ",ans[i]);
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值