Codeforces Round #649 (Div. 2) A-D

A:如果sm是k的倍数,肯定左右删最少的数。删到不是k的倍数的数即可

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
const double PI= acos(-1.0);
const int M = 1e5+7;
/*
int head[M],cnt;
void init(){cnt=0,memset(head,0,sizeof(head));}
struct EDGE{int to,nxt,w;}ee[M*2];
void add(int x,int y,int w){ee[++cnt].nxt=head[x],ee[cnt].w=w,ee[cnt].to=y,head[x]=cnt;}
*/
int a[M];
int main()
{
	ios::sync_with_stdio(false);
  	cin.tie(0);
  	int t;
  	cin>>t;
  	while(t--)
  	{
  		int n,x;
  		cin>>n>>x;
  		ll sm=0;
  		for(int i=1;i<=n;i++)cin>>a[i],sm+=a[i];
  		int mx=-1;
  		for(int i=1;i<=n;i++)
  		{
  			if(a[i]%x!=0)
  			{
  				mx=max(mx,n-i);
  				break;
			}
		  }
		for(int i=n;i>=1;i--)
  		{
  			if(a[i]%x!=0)
  			{
  				mx=max(mx,i-1);
  				break;
			}
		}
		if(sm%x!=0)
  		{
  			cout<<n<<endl;
		}
		else
		{
			cout<<mx<<endl;
		}
	}
	return 0;
}

B:

差分和最大,递增或递减序列时差分固定,(只要首末的数选上)

所以我们只保留波浪的峰点即可。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
const double PI= acos(-1.0);
const int M = 1e5+7;
/*
int head[M],cnt;
void init(){cnt=0,memset(head,0,sizeof(head));}
struct EDGE{int to,nxt,w;}ee[M*2];
void add(int x,int y,int w){ee[++cnt].nxt=head[x],ee[cnt].w=w,ee[cnt].to=y,head[x]=cnt;}
*/
int a[M];
int main()
{
	ios::sync_with_stdio(false);
  	cin.tie(0);
  	int t;
  	cin>>t;
  	while(t--)
  	{
  		int n;
  		cin>>n;
  		for(int i=1;i<=n;i++)
  			cin>>a[i];
  		bool f=true;
  		vector<int>v;
  		v.pb(a[1]);
  		if(a[2]>a[1])f=true;
  		else f=false;
		for(int i=3;i<=n;i++)
		{
			if(!f)
			{
				if(a[i]>a[i-1])
				{
					v.pb(a[i-1]);
					f=true;
				}
			}
			else
			{
				if(a[i]<a[i-1])
				{
					v.pb(a[i-1]);
					f=false;
				}
			}
		}
		v.pb(a[n]);
		cout<<v.size()<<endl;
		for(int i=0;i<v.size();i++)
		cout<<v[i]<<" ";
		cout<<endl;
	}
	return 0;
}

C:

贪心的放即可,题目已经满足a[i]<i,所以一定可以构造出。

先记录最后一个数(肯定是最大的数)所需的数,然后在每个相同数区间的首位放前面一个数需要的最大的数。

比如 1 1 2 2 3 6  

我们先放的数为:0 x 1 x 2 3 

这样保证每个数都不会在它的时候mex到它。

然后就把需要的集合从小往大放即可。(这个例子需要0 1 2 3 4 5),

0 4 1 5 2 3 

放满后其余数补n+1即可。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
#define in insert
const double PI= acos(-1.0);
const int M = 1e5+7;
/*
int head[M],cnt;
void init(){cnt=0,memset(head,0,sizeof(head));}
struct EDGE{int to,nxt,w;}ee[M*2];
void add(int x,int y,int w){ee[++cnt].nxt=head[x],ee[cnt].w=w,ee[cnt].to=y,head[x]=cnt;}
*/
int a[M],b[M];
int nxt[M];
set<int>s;
int main()
{
	ios::sync_with_stdio(false);
  	cin.tie(0);
  	int n;
  	cin>>n;
  	for(int i=1;i<=n;i++)
  	{
  		cin>>a[i];
  		b[i]=-1;
	}
	for(int i=0;i<a[n];i++)s.in(i);
	a[n+1]=a[n]+1;
	//for(int i =0;i<=n;i++)nxt[i]=upper_bound(a+1,a+1+n,a[i])-a;
	for(int i=2;i<=n;i++)
	{
		if(a[i]!=a[i-1])
		{
			b[i]=a[i-1];
			s.erase(b[i]);
		}
	}
	for(int i=1;i<=n;i++)
	{
		if(b[i]==-1)
		{
			int tp=n+1;
		//	cout<<i<<" "<<s.size()<<endl;
			for(auto x:s)
			{
				if(x==a[i])continue;
				tp=x;
				break;
			}
			s.erase(tp);
			b[i]=tp;
		}
	}
	for(int i=1;i<=n;i++)cout<<b[i]<<" ";
	cout<<endl;
	return 0;
}

D:

这题实现比较简单:

说下思路:

首先如果图是一个树,则:找到一个节点数为k/2的独立集很简单 (直接染色即可)

否则我们一定能找到一个环。

1.如果环大小大于k,则把环断开,拆成点数至少为k的树,可以找到符合条件的独立集

2.小于等于k,找到满足题意的环

到此这题做出来了。。

我们用dfs树找环并判断环大小即可。

后者的做法可以精确判断每个环的大小,方便起见采取后者。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
const double PI= acos(-1.0);
const int M = 2e5+7;
 
 
int head[M],cnt;
void init(){cnt=0,memset(head,0,sizeof(head));}
struct EDGE{int to,nxt,w;}ee[M*2];
void add(int x,int y,int w){ee[++cnt].nxt=head[x],ee[cnt].w=w,ee[cnt].to=y,head[x]=cnt;}
 
int T,n,m;
vector<int> vec,ans;
int dep[M],tag[M];
void dfs(int x) {
    vec.pb(x);
    dep[x] = vec.size();
   // cout<<x<<" "<<endl;
    for (int i = head[x];i;i = ee[i].nxt) 
	{
        int v = ee[i].to;
        if (!dep[v])dfs(v);
        else if (dep[x]-dep[v] < T && dep[x]-dep[v]>=2) 
		{
            cout << 2 << endl;
            cout << dep[x]-dep[v]+1 << endl;
            for (int j = dep[v]-1;j < dep[x];j++)
                cout << vec[j] << " ";
            cout << endl;
            exit(0) ;
        }
    }
    if (!tag[x]) 
	{
        ans.pb(x);
        for (int i = head[x];i;i = ee[i].nxt) 
		{
            int v = ee[i].to;
            tag[v] = 1;
        }
    }
    vec.pop_back();
}
 
int main() 
{
    ios::sync_with_stdio(false);
  	cin.tie(0);
    cin>>n>>m>>T;
    for (int i=1;i<=m;i++) 
	{
        int u,v;
        cin >> u >> v;
        add(u,v,1);
        add(v,u,1);
    }
    dfs(1);
    cout << 1 << endl;
    for (int i = 0;i < (T+1)/2;i++)
        cout << ans[i] << " ";
    cout << endl;
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值