CF Round #536 (Div. 2)

ACM题集:https://blog.csdn.net/weixin_39778570/article/details/83187443
题目链接:https://codeforces.com/contest/1106

A
模拟,输出十字型X的数量 
#include<bits/stdc++.h>
#define ll long long
#define fo(i,j,n) for(register int i=j; i<=n; i++)
using namespace std; 
int n;
char a[600][600];
int main(){
	cin>>n;
	fo(i,1,n){
		getchar(); 
		fo(j,1,n){
			scanf("%c",&a[i][j]);
		}
	}
	int ans =0;
	fo(i,1,n)fo(j,1,n){
		if(a[i][j]=='X'&&a[i-1][j-1]=='X'&&a[i-1][j+1]=='X'&&a[i+1][j-1]=='X'&&a[i+1][j+1]=='X'){
			ans++;
		}
	}
	cout<<ans;
	return 0;
} 
C
一堆数,分为多个集合(里面至少有两个数),si表示第i个集合的数的和
最小化 ∑si*si 
根据排列不等式...(不清楚...)
把最大和最小的归到一个集合里,集合里就两个数,共n/2个集合,所求结果最小 
#include<bits/stdc++.h>
#define ll long long
#define fo(i,j,n) for(register int i=j; i<=n; i++)
using namespace std; 
int n;
ll ans = 0;
ll a[300005];
int main(){
	cin>>n;
	fo(i,1,n)cin>>a[i];
	sort(a+1,a+1+n);
	if(n%2==0){
		int t=n/2;	
		fo(i,1,t){
			ans += (a[i]+a[n-i+1])*(a[i]+a[n-i+1]);
		}
	}else{
		int t=n/2;		
		t--;
		fo(i,1,t){
			ans += (a[i]+a[n-i+1])*(a[i]+a[n-i+1]);
		}
		ans +=(a[n+1]+a[n+2]+a[n+3])*(a[n+1]+a[n+2]+a[n+3]);
	} 
	cout<<ans;
}
B
给定n中鱼的数量和价格
m个客人
客人指定了他要的鱼和鱼的数量,如果要的鱼不够,则用最便宜的鱼补上。
如果有一种鱼没有被提供,客人就不开心,输出0,否则输出客人应该要付的钱 
#include<bits/stdc++.h>
#define ll long long
#define fo(i,j,n) for(register int i=j; i<=n; i++)
using namespace std; 
struct node{
	ll num,c,idx;
	bool operator<(const node&p)const{
		return c<p.c;
	}
}a[100005];
int n,m;
int idx[100005];
int main(){
	cin>>n>>m;
	fo(i,1,n){
		cin>>a[i].num;
		a[i].idx = i;
	}
	fo(i,1,n){
		cin>>a[i].c;
	}
	sort(a+1,a+1+n);
	fo(i,1,n){
		idx[a[i].idx]=i; // 原数组下标,映射到新数组下标 
	}
	int nxt = 1;
	fo(i,1,m){
		ll ans =0,t=0,d=0;
		cin>>t>>d;
		if(a[idx[t]].num>=d){ // 自己要的鱼够 
			ans = a[idx[t]].c*d;
			cout<<ans<<endl;
			a[idx[t]].num-=d;
		}else{// 自己要的鱼不够,吃最便宜的鱼 
			d -= a[idx[t]].num;
			ans = a[idx[t]].num*a[idx[t]].c;
			a[idx[t]].num = 0;
			fo(i,nxt,n){
				if(a[i].num>=d){
					ans += a[i].c*d;
					a[i].num -= d;
					d = 0;
					nxt=i;
				}else{
					ans += a[i].c*a[i].num;
					d -= a[i].num;
					a[i].num=0;
				}
				if(d<=0)break;
			}
			if(d){ // 拿不到鱼,不开心了 
				cout<<0<<endl;
			}else{
				cout<<ans<<endl;
			}
		}
	}
	return 0;
}
D
给一副无向图
输入字典顺序最小的遍历顺序,一个点到达一次,
但是可以多次路过(只算第一次到达)
----------------------------------------------
显然,从1出发最好
下一次要去的城市为现在能去的所有城市中选择一个字典序最小的城市
输出 

写法一:

#include<bits/stdc++.h>
#define ll long long
#define fo(i,j,n) for(register int i=j; i<=n; ++i)
using namespace std;
int n,m,x,y;
vector<int>G[100006],ans;
bool vis[100006];
int main(){
	cin>>n>>m;
	fo(i,1,m){
		cin>>x>>y;
		G[x].push_back(y);
		G[y].push_back(x);
	}
	priority_queue<int, vector<int>, greater<int> >pq;
	pq.push(1);
	vis[1] = 1;
	while(!pq.empty()){
		int u = pq.top();pq.pop();
		ans.push_back(u);
		for(int v:G[u]){
			if(!vis[v]){
				vis[v] = 1;
				pq.push(v);
			}
		}
	}
	for(int i=0; i<ans.size(); i++){
		printf("%d%c",ans[i],i==ans.size()-1?'\n':' ');
	}
	return 0;
}

写法二

#include<bits/stdc++.h>
#define ll long long
#define fo(i,j,n) for(register int i=j; i<=n; i++)
using namespace std; 
const int maxn = 100005;
int n,m;
vector<int>G[maxn],ans; 
bool vis[maxn];
set<int> s;
set<int>::iterator it,ed;
void dfs(int u){
	ans.push_back(u);
	vis[u]=1;
	for(int v:G[u]){
		if(!vis[v]){
			s.insert(v);	
		}
	}
//	for(it = s.begin(); s.size()>0&&it!=s.end(); it=s.begin()){
//		int v = *it;
//		s.erase(it);
//		dfs(v);
//	}
	if(s.size()){
		int v = *(s.begin());
		s.erase(s.begin());
		dfs(v);
	}
}
int main(){
	cin>>n>>m;
	fo(i,1,m){
		int x,y;
		cin>>x>>y;
		G[x].push_back(y);
		G[y].push_back(x);
	}
	fo(i,1,n){
		sort(G[i].begin(),G[i].end());
	}
	dfs(1);
	for(int i=0; i<ans.size(); i++){
		printf("%d%c",ans[i],i==ans.size()-1?'\n':' ');
	}
	return 0;
}
E
小A收集红包
每个红包有几个属性 L,R,D,C
表示在时间[L,R]内能收集,收集结束时间为D,红包大小为C
同一时刻小A优先收集C大的,一样大则收集D大的,都一样大则任意收集一个
小B要破坏小A的收集计划,他能破坏m次,比如在时间X破坏,
则小A在时间X就不能收集到红包
问小A最少收集到多少红包
---------------------------------------------------------------------
先预处理出小A在每个时刻要收集的红包
f[i][j] 表示收集到第i个时刻使用j次干扰收集到的最小钱数
一个惊人的事实,f[大数据][小数据] 这样初始化比f[小数据][大数据]慢很多
#include<bits/stdc++.h>
#define ll long long
#define fo(i,j,n) for(register int i=j; i<=n; ++i)
using namespace std;
const int maxn = 100005;
struct node{
	ll w,d;
	bool operator < (const node& p)const{
		if(w!=p.w)return w>p.w;
		else return d>p.d;
	}
}p,a[maxn];
int n,m,k,l,r;
multiset<node> mp;
vector<node> s[maxn],t[maxn];
ll f[maxn][205]; 
// 一个惊人的事实,f[大数据][小数据] 这样初始化比f[小数据][大数据]慢很多 
void init(){
	// 预处理出要拿的红包 
	fo(i,1,n){
		// 加入新的能拿的红包 
		for(auto x:s[i]){
			mp.insert(x);
		}
		// 去掉不能拿的红包 
		for(auto x:t[i]){
			mp.erase(mp.find(x));
		}
		if(!mp.empty()){
			a[i] = *mp.begin();
		}else{
			a[i] = node{0,i+1};
		} 
	}
}
void solve(){
	init();
	ll ans = 1e18;
	// 阶段性有终点倒叙 
	for(int i=n; i>=1; i--){ // 时刻 
		fo(j,0,m){ // 干扰 
			f[i][j] =  f[a[i].d][j]+a[i].w; // 不干扰 
			if(j) f[i][j] = min(f[i][j], f[i+1][j-1]);	//干扰 
		}
	}
	fo(j,0,m)ans = min(ans,f[1][j]);
	cout<<ans<<endl;
}
void solve2(){
	init();
	ll ans = 1e18;
	fo(j,0,m){
		for(int i=n; i>=1; i--){
			f[i][j] =  f[a[i].d][j]+a[i].w; // 不干扰 
			if(j) f[i][j] = min(f[i][j], f[i+1][j-1]);	//干扰 
		}
	}
	fo(j,0,m)ans = min(ans,f[1][j]);
	cout<<ans<<endl;
} 
void solve3(){
	init();
	long long ans = 1ll << 60;
	memset(f, 0x3f, sizeof(f));
	f[1][0] = 0; // 1时刻0干扰 
	for (int i = 0; i <= m; ++i) {
		for (int j = 1; j <= n; ++j)
			f[a[j].d][i] = min(f[a[j].d][i], f[j][i] + a[j].w);
		for (int j = 1; j <= n; ++j) f[j + 1][i + 1] = min(f[j + 1][i + 1], f[j][i]);
		ans = min(ans, f[n+1][i]);
	}

	cout << ans << endl;
}
int main(){
	scanf("%d%d%d",&n,&m,&k);
	fo(i,1,k){
		scanf("%d%d%lld%lld",&l,&r,&p.d,&p.w); 
	//	cin>>l>>r>>p.d>>p.w;
		p.d++; // 拿了红包的结束时间 
		s[l].push_back(p);   // 开始拿红包 
		t[r+1].push_back(p); // 结束拿红包 
	}
	solve3();
	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值