首页 > 其他分享 >CFR-850-Div-1解题报告

CFR-850-Div-1解题报告

时间:2023-03-01 15:55:13浏览次数:52  
标签:850 int auto back si 怪物 ans Div CFR

比赛传送门

A. Monsters (easy version)

题意:有 \(n\) 个怪物,每个有 \(a_i\) 滴血,每次可以选择一个怪物减一滴血,也可以“让所有怪物减一滴血,且如果杀死怪物则重复操作”。其中,第二种攻击只能使用一次。问杀死所有怪物,使用第一种攻击的最小次数。

显然要让第二种攻击发挥最大效果,就要让所有怪物的血量连续,一次杀掉所有怪物。可以从小到大排序后依次考虑每个怪物,如果扫到一个怪物的血量比目前连续的最大血量高,则攻击到最大血量\(+1\)。

By Mr_Eight

int n,a[200002];
int main() {
	F(adsf,1,read()){
		cin>>n;
		F(i,1,n)read(a[i]);
		sort(a+1,a+n+1);
		int now=0;
		ll ans=0;
		F(i,1,n){
			++now;
			now=min(now,a[i]);
			ans+=a[i]-now;
		}
		write(ans,'\n');
	}
	return 0;
}

B. Letter Exchange

题意:有 \(n\) 个人和 \(3\) 种卡片,每种各 \(n\) 张。每人初始有 \(3\) 张卡片,每次操作可以让两人各处一张卡片互换。问让每人都集齐 \(3\) 种卡片的最小操作数,输出方案。

可以将每个人拥有卡片的情况存到 \(vector\) 里,其中 \(v[i][j]\) 存所有多了 \(i\) 且少了 \(j\) 的人的编号。对于 \(000\) 类型的人,在 \(v[0][1]\) 和 \(v[0][2]\) 中各出现一次即可。

显然应该尽可能多地让 \(v[i][j]\) 和 \(v[j][i]\) 的人互换,且所有互换相互独立,直接处理即可。剩下的人一定不存在长度为 \(2\) 的交换环,所以考虑长度为 \(3\) 的,即 \(v[i][j],v[j][k],v[k][i]\)。这里只需要两次交换即可归位,且与外界独立。将两个方向的交换环分别处理即可。由于一共只有三种卡片且每种 \(n\) 张,经过这两步一定可以归位。

By maroonrk

const string win="win";

void slv(){
	int n;cin>>n;
	vi g[3][3];
	rep(i,n){
		string s;cin>>s;
		int cnt[3]{};
		for(auto c:s){
			cnt[win.find(c)]++;
		}
		vi u,v;
		rep(j,3)if(cnt[j]==0){
			v.pb(j);
		}else{
			rep(_,cnt[j]-1)u.pb(j);
		}
		assert(si(u)==si(v));
		rep(j,si(u)){
			g[u[j]][v[j]].pb(i);
		}
	}
	vc<tuple<int,int,int,int>> ans;
	rep(i,3)rep(j,i){
		while(si(g[i][j])&&si(g[j][i])){
			auto x=g[i][j].back();g[i][j].pop_back();
			auto y=g[j][i].back();g[j][i].pop_back();
			ans.eb(x,y,i,j);
		}
	}
	auto work=[&](int i,int j,int k){
		assert(si(g[i][j])==si(g[j][k]));
		assert(si(g[i][j])==si(g[k][i]));
		while(si(g[i][j])){
			auto x=g[i][j].back();g[i][j].pop_back();
			auto y=g[j][k].back();g[j][k].pop_back();
			auto z=g[k][i].back();g[k][i].pop_back();
			ans.eb(x,y,i,j);
			ans.eb(y,z,i,k);
		}
	};
	work(0,1,2);
	work(0,2,1);
	print(si(ans));
	for(auto [x,y,i,j]:ans){
		cout<<x+1<<" "<<win[i]<<" "<<y+1<<" "<<win[j]<<"\n";
	}
}

C. Monsters (hard version)

题意:杀敌的方式与 A 题相同,区别在于对于每个 \(k\),要求出假设只有前 \(k\) 个怪物时的最小次数。

做法一

可以倒序考虑。首先像第一题一样处理出所有 \(n\) 个怪物的方案,并把“没有发挥作用的”扔到 multiset 里。

从后往前依次删除怪物,维护当前“连续”到多少(假设为 \(x\)),以及所有“发挥作用”的怪物血量之和(\(sum\))。答案即为 \(sum-\frac{x(x+1)}{2}\)。

当删除一个怪物时,如果存在“没有发挥作用的”血量值相同的怪物,则直接从 multiset 里删除一个即可,答案不会改变。否则,这个怪物是发挥作用的怪物。将其删掉后 \(sum\) 减去该血量。\(x\) 是否要减去 \(1\) 呢?如果该血量之后存在一个最近的没有发挥作用的怪物,则其会变为发挥作用(从 multiset 中删掉),从而导致连续的长度不变。如果该血量之后所有怪物都已经发挥作用,则连续的长度会减小(\(x\) 减去 \(1\))。

By fireskydd

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,k,a[200004];ll b[200004];
multiset<int>s;ll ans;
void sol(){
	scanf("%d",&n),s.clear(),ans=0,k=0;
	for(int i=1;i<=n;i++)scanf("%d",&a[i]),s.insert(a[i]);
	for(;;){
		k++;auto it=s.lower_bound(k);
		if(it==s.end()){k--;break;}
		ans+=*it,s.erase(it);
	}
	for(int i=n;i;i--){
		b[i]=ans-(ll)k*(k+1)/2;
		auto it=s.lower_bound(a[i]);
		if(it!=s.end()&&*it==a[i])s.erase(it);
		else{
			ans-=a[i];
			if(it==s.end())k--;
			else ans+=(*it),s.erase(it);
		}
	}
	for(int i=1;i<=n;i++)printf("%lld ",b[i]);puts("");
}
int main(){
	int tc;scanf("%d",&tc);
	while(tc--)sol();
}

做法二

标签:850,int,auto,back,si,怪物,ans,Div,CFR
From: https://www.cnblogs.com/cxm1024/p/17168434.html

相关文章

  • EDU-CFR-115-Div-2解题报告
    赛时AC3道,补题做出来一道A.ComputerGame\(Problem\)有一个\(2\timesn\)的01矩阵,1为障碍,你要从\((1,1)\)走到\((2,n)\),每一步只能向右、上、下、右上、右下走,问......
  • EDU-CFR-116-Div-2解题报告
    比赛传送门做出来五道题。A.ABBalance{%noteinfono-iconproblem%}给你一个只含有a和b的字符串,问怎样通过修改尽可能少的字符,使得ab的数量和ba的数量相......
  • EDU-CFR-138解题报告
    比赛传送门A.CowardlyRooks题意:有一个\(n\timesn\)的棋盘,有\(m\)个位置上有车,保证互不攻击。问是否能将一个车移动一次使得仍然互不攻击。稍加思考可得,如果\(......
  • EDU-CFR-143解题报告
    A.TwoTowers题意:有两个积木塔,由红色/蓝色积木组成,你每次可以将一个塔的塔顶放到另一个塔上,问任意次操作后能否使得两座塔都是红蓝相间。可以将一个塔全部转移到另一......
  • 【比赛记录】 Codeforces Round #706 Div.2
    Problems:#NameSubmitASplitit!BMaxandMexCDiamondMinerDLet'sGoHikingEGardenoftheSunFBFSTrees题解:A:Splitit!判......
  • Educational Codeforces Round 143 (Rated for Div
    EducationalCodeforcesRound143(RatedforDiv.2)Problem-BIdealPoint给定n个线段区间\([l,r]\),我们定义\(f(x)\)为覆盖点\(x\)的线段数,我们每次操作可以删......
  • Codeforces Round #254 (Div. 1) C - DZY Loves Colors 线段树|lazytag维护区间加
    开一个变量维护同一个区间内颜色是否相同,而且显然要用lazytag了递归到颜色相同的区间时就可以直接打标记然后对于标记,维护的就是常规区间加的部分(最开始没写lazy,wa6,没明......
  • Codeforces Round #854 by cybercats (Div. 1 + Div. 2) A-B题解
    比赛链接A可以发现,每次出去的顺序一定是按照\(n->1\)的顺序。因为新加入的东西只会放在最前面。相应的,如果其已在序列中,则这个操作不会对\(1~n\)的信息产生影响。......
  • Educational Codeforces Round 143 (Rated for Div. 2)(A,C,D)
    EducationalCodeforcesRound143(RatedforDiv.2)(A,C,D)好久没有写题了,这次\(vp\)竟然连\(vs\)都不会用了,O(∩_∩)OAA这个也是差一点了,还有一个情况我的解法是没有......
  • Codeforces Round #854 by cybercats (Div. 1+2) 1799 A~G 题解
    点我看题A.RecentActions注意到只有编号大于n的博客会被更新,所以每当有一个之前没被更新的过的博客被更新时,当前列表中最下面的就会被挤掉。如果这次更新的博客之前已......