Codeforces Round #722 (Div. 2)(ABCD)

A.Eshag Loves Big Arrays(贪心)

统计最小的数出现次数为cnt 则答案为n-cnt
因为每次都可以一个最小的数加一个大的数来消掉大的数

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define pii pair<int,int>
const int N=1e5+10;


void solve()
{
	map<int,int>m;
	int n;
	cin>>n;
	int mi=105;
	for(int i=1;i<=n;i++)
	{
		int x;
		cin>>x;
		m[x]++;
		mi=min(mi,x);
	}
	cout<<n-m[mi]<<endl;
}
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		solve();
	}
	return 0;
}

B.Sifid and Strange Subsequences(贪心)

首先把负数和0都拿。然后计算这些数里面距离最近的值C(排序以后On可以算出来)。如果有正数小于等于C,那么答案加一。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define pii pair<int,int>
const int N=1e5+10;

int a[N];
void solve()
{
	int n;
	cin>>n;
	int ans=0,c1=0,c0=0;
	vector<pii>v;
	for(int i=0; i<n; i++)
	{
		int x;
		cin>>x;
		a[i]=x;
		if(x<=0)v.push_back({x,i}),ans++;
	}
	int mi=2e9;
	sort(v.begin(),v.end());
	for(int i=1; i<v.size(); i++)
	{
		mi=min(mi,abs(v[i].first-v[i-1].first));
	}
	for(int i=0; i<n; i++)
	{
		if(a[i]>0&&a[i]<=mi)
		{
			ans++;
			break;
		}
	}
	if(v.empty())ans=1;
	printf("%d\n",ans);
}
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		solve();
	}
	return 0;
}

C.Parsa’s Humongous Tree(树形dp)

树形dp模板题,首先要猜到每个点一定是取l或者r。因为如果枚举l到r的话复杂度就爆炸了嘛!然后就有dp方程
f [ i ] [ 2 ] f[i][2] f[i][2]表示 i 节点取 l或者r的最大值。然后枚举一下儿子是取什么转移即可
f [ u ] [ 0 ] + = m a x ( f [ i ] [ 0 ] + a b s ( l [ u ] − l [ i ] ) , f [ i ] [ 1 ] + a b s ( l [ u ] − r [ i ] ) ) ; f[u][0]+=max(f[i][0]+abs(l[u]-l[i]),f[i][1]+abs(l[u]-r[i])); f[u][0]+=max(f[i][0]+abs(l[u]l[i]),f[i][1]+abs(l[u]r[i]));
f [ u ] [ 1 ] + = m a x ( f [ i ] [ 0 ] + a b s ( r [ u ] − l [ i ] ) , f [ i ] [ 1 ] + a b s ( r [ u ] − r [ i ] ) ) ; f[u][1]+=max(f[i][0]+abs(r[u]-l[i]),f[i][1]+abs(r[u]-r[i])); f[u][1]+=max(f[i][0]+abs(r[u]l[i]),f[i][1]+abs(r[u]r[i]));
最终答案为 m a x ( f [ 1 ] [ 0 ] , f [ 1 ] [ 1 ] ) max(f[1][0],f[1][1]) max(f[1][0],f[1][1])

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define pii pair<int,int>
const int N=1e5+10;
ll f[N][2],l[N],r[N];
vector<int>g[N];
void dfs(int u,int fa)
{
	for(auto i:g[u])
	{
		if(i==fa)continue;
		dfs(i,u);
		f[u][0]+=max(f[i][0]+abs(l[u]-l[i]),f[i][1]+abs(l[u]-r[i]));
		f[u][1]+=max(f[i][0]+abs(r[u]-l[i]),f[i][1]+abs(r[u]-r[i]));
	}
}
void solve()
{
	int n;
	cin>>n;
	memset(f,0,sizeof f);
	for(int i=1;i<=n;i++)scanf("%lld%lld",&l[i],&r[i]),g[i].clear();
	for(int i=1;i<=n-1;i++)
	{
		int u,v;
		scanf("%d%d",&u,&v);
		g[u].push_back(v);
		g[v].push_back(u);
	}
	dfs(1,0);
	printf("%lld\n",max(f[1][0],f[1][1]));
}
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		solve();
	}
	return 0;
}

D.Kavi on Pairing Duty(递推)

先考虑不是全部长度都一样长的方案数
当前枚举到n。那么连1和2n以后,2~2n-1这段位置就是n-1的答案,连1和2n再连2和2n-1以后,
3~2*n-2这段就是n-2的答案。所以有个取前缀答案的过程。
在这里插入图片描述

然后考虑全部长度都一样长的方案数
会发现对于n。全部不交叉长度一样的有一种。ling
在这里插入图片描述
对于有交叉,长度一样的个数。画图后发现是n的因子个数-1。求因子个数用线性筛或者埃式筛都可以
在这里插入图片描述
具体看代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define pii pair<int,int>
const int N=1e6+10,mod=998244353;
int prime[N],cnt;
bool st[N];
ll num[N],d[N],f[N];
void ini()
{
	num[1]=1;
	d[1]=1;
	for(int i=2;i<N;i++)
	{
		if(!st[i])
		{
			prime[cnt++]=i;
			d[i]=1;
			num[i]=2;
		}
		for(int j=0;prime[j]<=N/i;j++)
		{
			st[i*prime[j]]=1;
			if(i%prime[j]==0)
			{
				d[i*prime[j]]=d[i]+1;
				num[i*prime[j]]=num[i]/(d[i]+1)*(d[i]+2);
				break;
			}
			d[i*prime[j]]=1;
			num[i*prime[j]]=num[i]*2;
		}
	}
}
void solve()
{
	int n;
	scanf("%d",&n);
	printf("%lld\n",f[n]%mod);
	
}
int main()
{
	ini();
	f[1]=1;
	ll sum=1;
	for(int i=2;i<N;i++)
	{
		f[i]=(sum+num[i])%mod;
		sum=(sum+f[i])%mod;
	}
	solve();
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值