Codeforces Round #670 (Div. 2)

A:直接贪心取即可

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define re register
#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=1;
void init(int n){cnt=1;for(int i=0;i<=n;i++)head[i]=0;}
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[110];
int main()
{
	ios::sync_with_stdio(false);
  	cin.tie(0);
  	int T;
	  cin>>T; 
	while(T--)
	{
		int n,x;
		cin>>n;
		memset(a,0,sizeof(a));
		for(int i=1;i<=n;i++)cin>>x,a[x]++;
		int nm=2,n1=0,n2=0;
		for(int i=0;i<=100;i++)
		{
			if(a[i]>1&&nm>1)n2=i+1;
			nm=min(nm,a[i]);
			if(a[i]>0&&nm>0)n1=i+1;
			nm=min(nm,a[i]);
		}
		cout<<n1+n2<<endl;
	}
	return 0;
}

B:

dp或直接枚举负数个数更简单。。。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define re register
#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=1;
void init(int n){cnt=1;for(int i=0;i<=n;i++)head[i]=0;}
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;}
*/
ll a[M];
ll dp[M][6][2];
int main()
{
	ios::sync_with_stdio(false);
  	cin.tie(0);
  	int T;
	cin>>T; 
	while(T--)
	{
		ll n,n1=0,n2=0,nm=0,inf=1e15;
		cin>>n;
	//	for(int i=1;i<=n;i++)
	//	for(int j=1;j<=5;j++)
	//	dp[i][j][0]=inf,dp[i][j][1]=-inf;
		for(int i=1;i<=n;i++)cin>>a[i];
		dp[1][1][1]=dp[1][1][0]=a[1];
		for(int i=2;i<=n;i++)
		{
			dp[i][1][0]=min(a[i],dp[i-1][1][0]);
			dp[i][1][1]=max(a[i],dp[i-1][1][1]);
			for(int j=2;j<=min(5,i);j++)
			{
				
				dp[i][j][0]=min(dp[i-1][j-1][0]*a[i],dp[i-1][j-1][1]*a[i]);
				if(i>j)dp[i][j][0]=min(dp[i][j][0],dp[i-1][j][0]);
				dp[i][j][1]=max(dp[i-1][j-1][0]*a[i],dp[i-1][j-1][1]*a[i]);
				if(i>j)dp[i][j][1]=max(dp[i][j][1],dp[i-1][j][1]);
			}
		}
		cout<<dp[n][5][1]<<endl;
	}
	return 0;
}

C:

两个重心时一定是 最大联通块为n/2的情况,找到重心后破化他们即可。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define re register
#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=1;
void init(int n){cnt=1;for(int i=0;i<=n;i++)head[i]=0;}
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 vs[M],siz[M];
int n,ans,pos;
vector<int>s;
void dfs(int x)
{
	vs[x]=1;siz[x]=1;
	int mx=0;
	for(int i=head[x];i;i=ee[i].nxt)
	{
		int y=ee[i].to;
		if(vs[y])continue;
		dfs(y);
		siz[x]+=siz[y];
		mx=max(mx,siz[y]);
	}
	mx=max(mx,n-siz[x]);
	
	if(mx<ans)
	{
		ans=mx;
		pos=x;
		s.clear();
	}
	if(mx==ans)s.pb(x);
}
int main()
{
	ios::sync_with_stdio(false);
  	cin.tie(0);
  	int T;
  	cin>>T;
  	while(T--)
  	{
  		int u,v;
  		cin>>n;
  		for(int i=0;i<=n;i++)head[i]=0,vs[i]=0;
  		ans=n+1;cnt=1;pos=-1;
		for(int i=1;i<n;i++)cin>>u>>v,add(u,v,1),add(v,u,1);
		s.clear();
  		dfs(1);
//  		cout<<pos<<"   "<<ans<<endl;
//  		for(auto x:s)cout<<" - "<<x;cout<<endl;
  		if(s.size()==1)cout<<u<<" "<<v<<"\n"<<u<<" "<<v<<endl;
  		else
  		{
  			int p=s[0],q=s[1],t,o;
  			for(int i=head[p];i;i=ee[i].nxt)
  			{
  				int y=ee[i].to;
  				if(y==q)continue;
  				t=y;
			}
			cout<<p<<" "<<t<<endl;
			cout<<q<<" "<<t<<endl;
		}
	}
	return 0;
}

D:

假设最大值为x。

令c[1]=x, b[1]=a[1]-x;

然后贪心分配b,c数组。

对于a[j],cz=a[j]-a[j-1]

若cz>0,则为了让b数组尽量小,我们不改变c数组,直接b[j]=b[j-1]+cz;

若cz<0,则为了让b数组尽量小,我们不改变b数组,直接让c[j]=c[j-1]+cz;

上述变化都要满足b非递增,c非递减序列。

然后此时b数组最大的数为b[n]

显然有:b[n]<=c[1]

即:b[1]+zm<=x

即:2*x<=a[1]-zm;

zm为a的差分数组中正数的和。

我们只需要维护zm即可O1求出x

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define re register
#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=1;
void init(int n){cnt=1;for(int i=0;i<=n;i++)head[i]=0;}
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;}
*/
ll a[M],c[M];
ll zm,fm;
void gao(int x,int d)
{
	if(c[x]<0)fm-=c[x];else zm-=c[x];
	c[x]+=d;
	if(c[x]<0)fm+=c[x];else zm+=c[x];
}
int main()
{
	ios::sync_with_stdio(false);
  	cin.tie(0);
  	int n;
	  cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i],c[i]=a[i]-a[i-1];
		if(i==1)continue;
		if(c[i]>0)zm+=c[i];
		else fm+=c[i];
	}
	// a1=x+y  ;  x+zm<=y  2x<=a1-zm;
	ll ans=a[1]-(a[1]-zm-1)/2;
	cout<<ans<<endl;
	int q;
	cin>>q;
//	cout<<" =   "<<zm<<" "<<fm<<endl;
	while(q--)
	{
		int l,r,x;
		cin>>l>>r>>x;
		if(l>1)gao(l,x);
		if(r+1<=n)gao(r+1,-x);
	//	cout<<zm<<"  --   "<<fm<<"  "<<a[1]<<endl;
		if(l==1)a[1]+=x;
		ans=a[1]-(a[1]-zm-1)/2;
		cout<<ans<<endl;
	}
	return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值