Codeforces Round 892 (Div. 2)A~D

比赛链接

vp+补题

A.(结论)

显然,把所有最大的放在一个数组里,其他放在另一个数组里就行了,注意输出格式。

#include<iostream>
#include<set>
#include<map>
using namespace std;
const int N=2e5+10;
int T,n,a[N];
void solve(){
	cin>>n;
	int ma=-1e9;
	set<int>s;
	map<int,int>mp;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		ma=max(a[i],ma);
		mp[a[i]]++;
		s.insert(a[i]);
	}
	if(s.size()==1){
		cout<<-1<<endl;
		return;
	}
	else{
		int k=mp[ma];
		cout<<n-k<<' '<<k<<endl;
		for(int i=1;i<=n;i++)if(a[i]!=ma)cout<<a[i]<<' ';
		cout<<endl;
		while(k--)cout<<ma<<' ';
		cout<<endl;
		
	}
}
int main(){
	cin>>T;
	while(T--){
		solve();
	}
}

B(思维+数学)

题意,你可以任意移动数组中的元素到另外一个数组中, 经过若干次操作后。定义成本就是每个数组的最小值,然后加起来,最大化成本。我们的操作是把每行的最小值都塞到一个数组中。这样的话,成本就是所有行当前的最小值(原来的次小值)。若m是所有数的最小值,m3是所有次小值的最小值,m2为次小值,很显然ans=(\sum m_{2}^{})+m-m_{3}^{} 好像有点抽象哈(

#include<iostream>
#include<algorithm>
#include<vector>
#define int long long 
using namespace std;
const int N=2e5+10;
int T,n;
void solve(){
	vector<int>a;
	cin>>n;
	int m3=1e9,m=1e9;
	int ans=0;
	for(int i=1;i<=n;i++){
		int r;
		cin>>r;
		int m1=1e9,m2=1e9;
		for(int i=1;i<=r;i++){
			int x;
			cin>>x;
			m=min(x,m);
			if(x<m1){
				m2=m1;
				m1=x;
			}
			else if(x<m2)m2=x;
		}
		m3=min(m3,m2);
		ans+=m2;
	}
	ans+=m;
	ans-=m3;
	cout<<ans<<endl;
}
signed main(){
	cin>>T;
	while(T--){
		solve();
	}
}

C(数学,构造)

打表发现,当取得最大值的时候,一定满足如下形式:1 2 3 …… x n n-1 …… x+1 即前面一段是正序,后面一段是逆序,枚举从哪里开始是逆序即可,复杂度O(n^{2}),绰绰有余了。

#include<iostream>
using namespace std;
const int N=255;
int T,n,a[N],b[N];
void solve(){
	cin>>n;
	for(int i=1;i<=n;i++){
		a[i]=i;
	}
	for(int i=1;i<=n;i++)b[i]=n-i+1;
	///for(int i=1;i<=n;i++)cout<<b[i]<<' ';
	//cout<<endl;
	//枚举从哪里开始替换成n
	int ans=0;
	for(int now=n;now>=1;now--){
		int cnt=0;
		//cout<<now<<' ';
		for(int i=now;i<=n;i++){
			//cout<<1;
			//a[now]=b[++cnt];死因
			a[i]=b[++cnt]; 
		}
		//for(int i=1;i<=n;i++)cout<<a[i]<<' ';
		//cout<<endl;
		//计算当前的价值
		int ma=0,res=0;
		for(int i=1;i<=n;i++){
			res+=i*a[i];
			ma=max(ma,i*a[i]);
		}
		res-=ma;
		ans=max(ans,res);
	}
	cout<<ans<<endl;
}
int main(){
	cin>>T;
	while(T--){
		solve();
	}
}

D(区间合并+离线操作)

对于(l,r,a,b)满足l<=a<=b<=r,我们发现,若在b<x<r的区间内,我们使用传送,一定是不优的,而我们在[l,b],我们都可以直接到b,考虑区间合并,这样就把区间划分成了若干了不相交的区间。如果直接暴力询问,复杂度是O(nq)。我们发现,对于点x越大,我们最终能到的点也越大,离线即可。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
const int N=2e5+10;
int T,n,q;
struct node{
	int x,id;
}b[N];
typedef pair<int,int>pii;
bool cmp(node a,node b){
	return a.x<b.x;
}
void solve(){
	cin>>n;
	vector<pii>arr;
	vector<pii>ve;
	for(int i=1;i<=n;i++){
		int l,r,a,b;
		cin>>l>>r>>a>>b;
		arr.push_back(make_pair(l,b));
	}
	cin>>q;vector<int>ans(q+1);
	for(int i=1;i<=q;i++){
		cin>>b[i].x;
		b[i].id=i;
	}
	sort(b+1,b+q+1,cmp);
	sort(arr.begin(),arr.end());//从小到大排序
	for(int i=0;i<n;){
		int x=arr[i].first;
		int y=arr[i].second;
		while(i<n&&arr[i].first<=y){
			y=max(y,arr[i].second);
			i++;
		}
		ve.push_back(make_pair(x,y));//这样 区间就是相互独立的 
	}
	int now=0;int sz=ve.size();
	//cout<<"check:"<<ve[sz-1].second<<endl;
	for(int i=1;i<=q;i++){
		int pos=b[i].x;
		while(now<sz-1&&(pos>ve[now].second))now++;
		//now=sz-1;
		if(pos>=ve[now].first)pos=max(pos,ve[now].second);
		ans[b[i].id]=pos;
	}
	for(int i=1;i<=q;i++)cout<<ans[i]<<' ';
	cout<<endl;
}
signed main(){
	cin>>T;
	while(T--)solve();
	return 0;
}

————————————————The  END——————————————————————

  • 6
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值