Codeforces Round #670 (Div. 2) 题解 (ABCD)

A. Subset Mex

大意:把原数组分成俩数组A,B,求(最小的A里没出现的自然数+最小的B里没出现的自然数)的最大值

答案是最小的出现次数<2的自然数,加上最小的没出现的自然数

#include <bits/stdc++.h>
using namespace std;
#define repeat(i,a,b) for(int i=(a),_=(b);i<_;i++)
#define repeat_back(i,a,b) for(int i=(b)-1,_=(a);i>=_;i--)
#define mst(a,x) memset(a,x,sizeof(a))
#define fi first
#define se second
mt19937 rnd(chrono::high_resolution_clock::now().time_since_epoch().count());
int cansel_sync=(ios::sync_with_stdio(0),cin.tie(0),0);
const int N=200010; typedef long long ll; const int inf=~0u>>2; const ll INF=~0ull>>2; ll read(){ll x; if(scanf("%lld",&x)==-1)exit(0); return x;} typedef double lf; const lf pi=acos(-1.0); lf readf(){lf x; if(scanf("%lf",&x)==-1)exit(0); return x;} typedef pair<ll,ll> pii; template<typename T> void operator<<(vector<T> &a,T b){a.push_back(b);}
const ll mod=(1?1000000007:998244353); ll mul(ll a,ll b,ll m=mod){return a*b%m;} ll qpow(ll a,ll b,ll m=mod){ll ans=1; for(;b;a=mul(a,a,m),b>>=1)if(b&1)ans=mul(ans,a,m); return ans;}
#define int ll
map<int,int> mp;
void Solve(){
	int n=read(); mp.clear();
	repeat(i,0,n)mp[read()]++;
	int ans=0;
	repeat(i,0,inf)if(mp[i]<2){
		ans+=i;
		break;
	}
	repeat(i,0,inf)if(mp[i]<1){
		ans+=i;
		break;
	}
	cout<<ans<<endl;
}
signed main(){
	//freopen("data.txt","r",stdin);
	int T=1; T=read();
	repeat(ca,1,T+1){
		Solve();
	}
	return 0;
}

B. Maximum Product

大意:求数组中的五个数之积的最大值

最小的x个数和最大的5-x个数之积(x=0,1,2,3,4,5),这六个数取最大值

#include <bits/stdc++.h>
using namespace std;
#define repeat(i,a,b) for(int i=(a),_=(b);i<_;i++)
#define repeat_back(i,a,b) for(int i=(b)-1,_=(a);i>=_;i--)
#define mst(a,x) memset(a,x,sizeof(a))
#define fi first
#define se second
mt19937 rnd(chrono::high_resolution_clock::now().time_since_epoch().count());
int cansel_sync=(ios::sync_with_stdio(0),cin.tie(0),0);
const int N=200010; typedef long long ll; const int inf=~0u>>2; const ll INF=~0ull>>2; ll read(){ll x; if(scanf("%lld",&x)==-1)exit(0); return x;} typedef double lf; const lf pi=acos(-1.0); lf readf(){lf x; if(scanf("%lf",&x)==-1)exit(0); return x;} typedef pair<ll,ll> pii; template<typename T> void operator<<(vector<T> &a,T b){a.push_back(b);}
const ll mod=(1?1000000007:998244353); ll mul(ll a,ll b,ll m=mod){return a*b%m;} ll qpow(ll a,ll b,ll m=mod){ll ans=1; for(;b;a=mul(a,a,m),b>>=1)if(b&1)ans=mul(ans,a,m); return ans;}
#define int ll
vector<int> a;
void Solve(){
	int n=read(); a.clear();
	repeat(i,0,n)a<<read();
	#define b a.rbegin()
	sort(a.begin(),a.end());
	int ans=max({
		a[0]*a[1]*a[2]*a[3]*a[4],
		a[0]*a[1]*a[2]*a[3]*b[0],
		a[0]*a[1]*a[2]*b[1]*b[0],
		a[0]*a[1]*b[2]*b[1]*b[0],
		a[0]*b[3]*b[2]*b[1]*b[0],
		b[4]*b[3]*b[2]*b[1]*b[0]
	});
	cout<<ans<<endl;
}
signed main(){
	//freopen("data.txt","r",stdin);
	int T=1; T=read();
	repeat(ca,1,T+1){
		Solve();
	}
	return 0;
}

大意:给定一棵树,要求删掉一条边并加上一条边,满足得到的图仍然是一棵树并且重心的个数只有一个

首先找到其中一个重心a,然后找到这个重心的重儿子(子树最大的儿子)b,然后找到这个儿子的随便一个儿子c,去掉b-c添加a-c即可(特判b没有儿子的情况)

证明:一棵树最多只能有两个重心。如果原来只有一个重心,那么该操作只会增大b的最大子树大小,a显然还是是唯一重心;如果原来有两个重心,那么b就是原来另一个重心,该操作会增大b的最大子树大小并减小a最大子树大小,a就成为了唯一重心

#include <bits/stdc++.h>
using namespace std;
#define repeat(i,a,b) for(int i=(a),_=(b);i<_;i++)
#define repeat_back(i,a,b) for(int i=(b)-1,_=(a);i>=_;i--)
#define mst(a,x) memset(a,x,sizeof(a))
#define fi first
#define se second
mt19937 rnd(chrono::high_resolution_clock::now().time_since_epoch().count());
int cansel_sync=(ios::sync_with_stdio(0),cin.tie(0),0);
const int N=200010; typedef long long ll; const int inf=~0u>>2; const ll INF=~0ull>>2; ll read(){ll x; if(scanf("%lld",&x)==-1)exit(0); return x;} typedef double lf; const lf pi=acos(-1.0); lf readf(){lf x; if(scanf("%lf",&x)==-1)exit(0); return x;} typedef pair<ll,ll> pii; template<typename T> void operator<<(vector<T> &a,T b){a.push_back(b);}
const ll mod=(1?1000000007:998244353); ll mul(ll a,ll b,ll m=mod){return a*b%m;} ll qpow(ll a,ll b,ll m=mod){ll ans=1; for(;b;a=mul(a,a,m),b>>=1)if(b&1)ans=mul(ans,a,m); return ans;}
#define int ll
vector<int> a[N]; 
namespace center{
vector<int> rec;
int sz[N],maxx[N];
void dfs(int x,int fa=-1){
	rec<<x;
	sz[x]=1; maxx[x]=0;
	for(auto i:a[x]){
		int p=i;
		if(p!=fa){
			dfs(p,x);
			sz[x]+=sz[p];
			maxx[x]=max(maxx[x],sz[p]);
		}
	}
}
int get(int x){ //get center
	rec.clear(); dfs(x); int n=sz[x],ans=x;
	for(auto x:rec){
		maxx[x]=max(maxx[x],n-sz[x]);
		if(maxx[x]<maxx[ans])ans=x;
	}
	return ans;
}
}using namespace center;
void Solve(){
	int n=read(); repeat(i,1,n+1)a[i].clear();
	repeat(i,0,n-1){
		int x=read(),y=read();
		a[x]<<y; a[y]<<x;
	}
	int c=get(1);
	get(c);
	if(maxx[c]==1){
		cout<<c<<' '<<a[c][0]<<endl;
		cout<<c<<' '<<a[c][0]<<endl;
		return;
	}
	int p1,p2;
	for(auto i:a[c])if(maxx[c]==sz[i])p1=i;
	for(auto i:a[p1])if(c!=i)p2=i;
	cout<<p1<<' '<<p2<<endl;
	cout<<p2<<' '<<c<<endl;
}
signed main(){
	//freopen("data.txt","r",stdin);
	int T=1; T=read();
	repeat(ca,1,T+1){
		Solve();
	}
	return 0;
}

D. Three Sequences

大意:给定ai,令bi为单调不减序列,ci为单调不增序列,且ai=bi+ci。对a数组区间加操作,询问max(b1,b2,...,bn,c1,c2,...,cn)的最小值

设ai的差分数组为di。(具体思路写不了,太难讲了)发现答案只与di所有正数(或者负数)之和以及a1(或者an)有关。计算可得,令 \(a_n=lst,\sum_{d_i<0}d_i=dec\),答案就是 \(lst+\lfloor \dfrac{lst+dec}2\rfloor\)(形式不唯一)。维护lst和dec都简单的一批

#include <bits/stdc++.h>
using namespace std;
#define repeat(i,a,b) for(int i=(a),_=(b);i<_;i++)
#define repeat_back(i,a,b) for(int i=(b)-1,_=(a);i>=_;i--)
#define mst(a,x) memset(a,x,sizeof(a))
#define fi first
#define se second
mt19937 rnd(chrono::high_resolution_clock::now().time_since_epoch().count());
int cansel_sync=(ios::sync_with_stdio(0),cin.tie(0),0);
const int N=200010; typedef long long ll; const int inf=~0u>>2; const ll INF=~0ull>>2; ll read(){ll x; if(scanf("%lld",&x)==-1)exit(0); return x;} typedef double lf; const lf pi=acos(-1.0); lf readf(){lf x; if(scanf("%lf",&x)==-1)exit(0); return x;} typedef pair<ll,ll> pii; template<typename T> void operator<<(vector<T> &a,T b){a.push_back(b);}
const ll mod=(1?1000000007:998244353); ll mul(ll a,ll b,ll m=mod){return a*b%m;} ll qpow(ll a,ll b,ll m=mod){ll ans=1; for(;b;a=mul(a,a,m),b>>=1)if(b&1)ans=mul(ans,a,m); return ans;}
#define int ll
int a[N],b[N];
void Solve(){
	int n=read();
	repeat(i,1,n+1)a[i]=read();
	int lst=a[n],ans=0;
	auto up=[&](int x,int d=1){
		if(b[x]<0)ans+=d*b[x];
	};
	repeat(i,1,n){
		b[i]=a[i+1]-a[i];
		up(i);
	}
	int q=read();
	cout<<lst-llround((lst+ans)/2.0-0.1)<<endl;
	while(q--){
		int l=read(),r=read(),k=read();
		if(r==n)lst+=k;
		if(l!=1){
			up(l-1,-1);
			b[l-1]+=k;
			up(l-1,1);
		}
		if(r!=n){
			up(r,-1);
			b[r]-=k;
			up(r,1);
		}
		cout<<lst-llround((lst+ans)/2.0-0.1)<<endl;
	}
}
signed main(){
	//freopen("data.txt","r",stdin);
	int T=1; //T=read();
	repeat(ca,1,T+1){
		Solve();
	}
	return 0;
}
posted @ 2020-09-13 01:35  axiomofchoice  阅读(265)  评论(0编辑  收藏  举报