Codeforces Round #649 (Div. 2) ABC题解

A. XXXXX

**题目链接**
题意:找出数组a[]的最大子数组,只能从开头删除或结尾删除一定的元素。使得子数组和不可被x整除。
题解:分类删除便可,记录和和数组长度。

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <string>
#include <cmath>
#define ll long long
#define PI 3.141592653589
using namespace std;
ll n,k,i,j,m,x,ii,jj;
ll a[100005];
int main()
{
 int t;
 cin>>t;
    while(t--){
     cin>>n>>x;
     ll sum=0;
     for(i=1;i<=n;i++){
      cin>>a[i];
      sum+=a[i];
  }
  if(sum%x!=0) cout<<n<<endl;
  else {
   ll num=sum;
   jj=0;
   m=0;k=0;
   for(i=1;i<=n;i++)
   {
    sum-=a[i];
    if(sum%x!=0) {m=n-i;jj=1;break;} 
   }
   for(i=n,ii=1;i>0;i--){
    num-=a[i];
    if(num%x!=0) {k=n-ii;jj=1;break;} 
    ii++;
   }
   m=max(m,k);
   if(sum==0&&num==0) jj=0;
   if(jj)
   cout<<m<<endl;
   else cout<<"-1"<<endl;
  }
 }
 return 0;
}

B. Most socially-distanced subsequence

题目链接
题意:找出p[]的子序列,使得子序列差值的绝对值之和最大。即|s1−s2|+|s2−s3|+…+|sk−1−sk|最大。子序列长度最小为2。得到子序列最小。
题解:可以看出,得p[]序列在一定长度时为单调区间,只要找出这些单调区间并记录这个区间的开头结尾值便是新的长度最小的子序列。

#include<bits/stdc++.h>
#define ll long long
#define maxn 2010
#define frj(i,n,k) for(long long i=2;i<=n-k;i++)
#define mc(i,q,k) modC(i,q,k)
using namespace std;
ll n,k,t,m,x,i,sum,l,r;
ll a[100005],b[100005],c[100005];
int main()
{
     cin>>t;
     while(t--){
         cin>>n;
         a[0]=0;
         for(i=1;i<=n;i++)
          {
    cin>>a[i];
    b[i]=a[i]-a[i-1];
          } 
          k=0;m=1;
          c[k++]=a[1]; 
     for(i=2;i<n;i++){
        if(b[i]>0&&b[i+1]>0)  continue;
        else if(b[i]<0&&b[i+1]<0)   continue;
        else m++,c[k++]=a[i];
     }
     m++;c[k++]=a[n];
     cout<<m<<endl;
     for(i=0;i<k;i++) cout<<c[i]<<" ";
     cout<<endl;
   }
 return 0;
}
 

C. Ehab and Prefix MEXs

题目链接
题意:给定一个长度为N的数组,找出一个长度相同的数组,对于在 i (1≤i≤n)(1≤i≤n) MEX({b1, b2b2, ……, bi})=ai,使得MEX是不属于这个集合的最小非负整数。输出这个数组,有多个则输出任意一个。
题解:记录a数组的值,在N的长度里查看是否有这个值并记录i,最后用数组b[]来记录所得结果,判断是否能够满足条件并输出。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 50;
ll t,n,i,sum,num,m;
ll a[maxn],b[maxn],c[maxn],d[maxn],ans[maxn];
int main()
{
 ll x=0,y=0;
 cin>>n;
 for(i=1;i<=n;i++)
 cin>>a[i],ans[a[i]]++;
 for(i=0;i<a[n];i++)
   if(!ans[i]) d[++y]=i;
   else c[++x]=i;
  int n1=1,n2=1;
  for(i=1;i<=n;i++){
   if(n1<=x&&a[i]>c[n1]) b[i]=c[n1++];
   else if(n2<=y) b[i]=d[n2++];
   else b[i]=n+5;
  }
  memset(ans,0,sizeof ans);
  int now=-1;
  for(i=1;i<=n;i++){
   ans[b[i]]=1;
   while(ans[now+1]) now+=1;
   if(now+1!=a[i]){
    cout<<"-1"<<endl;
    return 0;
   } 
  } 
  for(i=1;i<=n;i++) cout<<b[i]<<" ";
 return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值