首页 > 其他分享 >CF Round946(div3) 题解

CF Round946(div3) 题解

时间:2024-05-30 22:12:32浏览次数:28  
标签:pq int 题解 void Round946 cin vector func div3

目录

946(div3)

A

每个屏幕3X5, 可放2个2X2, 其余可填7个1X1 先算2X2需要多少个屏幕,再算当前屏幕是否可放下所有1X1, 根据1X1的量加屏幕.

void func()
{
	int a,b;
	cin >> a >> b;
	int ans = (b+1) / 2;
	int stp = a - (ans*15 - 4*b);
	if(stp > 0)	ans += (stp + 14) / 15;
    //当前屏幕是否可以放下所有a,不能则再加屏幕. 
	cout << ans << '\n';
}

B

s为原字符串,r为s中字字母去重排序后字符串串. 题目需要求将s中每个字符根据r替换为r中对称字符后的字符串的原字符串. 实际操作可逆, 从s'得到s和从s得到s'的操作是一样的.
用s将r处理出来,再把对称字符互相映射用二分硬找也行,也是O(nlogn),输出替换的串即可.

void func()
{
	int n;
	string st;
	cin >> n >> st;
	vector<char> a(n);
	for(int i=0;i<n;++i)	a[i] = st[i];
	sort(a.begin(),a.end());//处理r
	a.erase(unique(a.begin(),a.end()),a.end());//去重函数
	int len = a.size();
	map<char,char> mp;//对称串映射
	for(int i=0;i<len;++i)
	{
		mp[a[i]] = a[len - 1 - i];
	}
	for(int i=0;i<n;++i)
	{
		st[i] = mp[st[i]];
	}
	cout << st << '\n';
}

C

数据最多可有1011, 要开longlong
解法1: 3map暴力O(nlogn)
找到连续三个字符的字符串中有一个不同的个数. 时间长且数据不大,开三个map分别存123号位不同的点即可. 统计其中两个位相同第三个位相同和不同的数目,相乘加入总数即可.
代码比较丑陋, 直接粘贴了三个for().

void func()
{
	int n;
	cin >> n;
	vector<int> v(n);
	map<pair<int,int>,vector<int>> mp1,mp2,mp3;//三个二元组映射vector, 根据其中两位映射第三位. 
	int a,b,c;
	for(auto &i : v) cin >> i;
	for(int i=0;i<n-2;++i)
	{
		mp1[{v[i],v[i+1]}].push_back(v[i+2]);// 存储
		mp2[{v[i],v[i+2]}].push_back(v[i+1]);
		mp3[{v[i+1],v[i+2]}].push_back(v[i]);
	}
	int cnt = 1,ans = 0;
	for(auto &i : mp1)//每次处理一组两位置相同的元素
	{
		sort(i.y.begin(),i.y.end());//排序,方便根据前一位统计有几个相同
		int size = i.y.size();
		for(int j=1;j<size;++j)
		{
			if(i.y[j] == i.y[j-1])	cnt++;
			else
			{
				ans += (size-cnt)*cnt;
				cnt = 1;
			}
		}
		ans += (size-cnt)*cnt;//可能最后一元素与前一个相同, 需单独处理
		cnt = 1;
	}
	//后二for()操作相同
	for(auto &i : mp2)
	{
		sort(i.y.begin(),i.y.end());
		int size = i.y.size();
		for(int j=1;j<size;++j)
		{
			if(i.y[j] == i.y[j-1])	cnt++;
			else
			{
				ans += (size-cnt)*cnt;
				cnt = 1;
			}
		}
		ans += (size-cnt)*cnt;
		cnt = 1;
	}
	for(auto &i : mp3)
	{
		sort(i.y.begin(),i.y.end());
		int size = i.y.size();
		for(int j=1;j<size;++j)
		{
			if(i.y[j] == i.y[j-1])	cnt++;
			else
			{
				ans += (size-cnt)*cnt;
				cnt = 1;
			}
		}
		ans += (size-cnt)*cnt;
		cnt = 1;
	}
	cout << ans/2 << '\n';
}

解法2: 容斥O(nlogn)
统计出12,13,23号位相同的可能性, 再减去123号位完全相同的可能.
注意: 在12,13,23三组,统计了三次123相同,所以最后结果需要减三个123.
容斥原理

void func()
{
	int n,ans1 = 0,ans2 = 0;
	cin >> n;
	map<pair<int,int>,int> cnt1,cnt2,cnt3;//分别存12, 13, 23相同的元素数目
	map<edge,int> cnt4;// 存三个元素完全相同的元素数目
	vector<int> v(n);
	for(int i=0;i<n;++i)	cin >> v[i];
	for(int i=0;i<n-2;++i)
	{
		cnt1[{v[i],v[i+1]}]++;
		cnt2[{v[i],v[i+2]}]++;
		cnt3[{v[i+1],v[i+2]}]++;
		cnt4[{v[i],v[i+1],v[i+2]}]++;
	}
	for(auto &i : cnt1)	ans1 += (i.y-1)*i.y/2;
	for(auto &i : cnt2)	ans1 += (i.y-1)*i.y/2;
	for(auto &i : cnt3)	ans1 += (i.y-1)*i.y/2;
	for(auto &i : cnt4)	ans2 += i.y*(i.y-1)/2;
	int ans = (ans1 - 3*ans2);
	cout << ans << '\n';
}

D

保证两者都进行过运动下直接暴力即可, 因为多个if太长了, 抄了会长的代码.
对于每种操作, 第一次给了H, 第二次就必须给R. 所以计算同类操作MOD2后是否相同来确定此方向下HR同位置. 另外, 将Y轴操作初试设为1, X轴操作设为0可以保证有解情况下两者一定进行了操作.

void func()
{
	int n;
	string st,ans;
	cin >> n >> st;
	int cnt = 0;// 确定都进行操作
	map<char,int> mp;
	mp['W'] = mp['E'] = 1;
	mp['N'] = mp['S'] = 0;
	for(int i=0;i<n;++i)
	{
		ans += (mp[st[i]] == 0 ? 'R' : 'H');
		if(ans[i] == 'R')	cnt |= 1;// R
		if(ans[i] == 'H')	cnt |= 2;// H
		mp[st[i]] ^= 1;
	}
	/*
	cnt | 1 | 2 == 3, 保证两者都进行操作
	N == S, W == E, 保证位置相同
	*/
	if(cnt == 3 && mp['N'] == mp['S'] && mp['W'] == mp['E'])	cout << ans << '\n';
	else	cout << "NO\n";
}

E

G

贪心, 如果当前金钱可以购买本月快乐, 则加入答案, 但是如果买本次快乐的钱足够买后面两次的, 那就不成立, 所以在遇到后续更便宜的快乐时替换掉, 总快乐不变但是余额变多.
其实是反悔贪心, 把每次加入的答案加入堆, 如果余额足够则加入, 不足则和堆最大值比较, 如果更小则替换最大值, 获得差值的金钱.

void func()
{
	int m,x;
	cin >> m >> x;
	vector<int> a(m);
	for(auto &i :a)	cin >> i;
	priority_queue<int> pq;// 大根堆
	int money = 0,happy = 0;
	for(int i=0;i<m;++i)
	{
		if(money >= a[i])
		{
			happy++;
			money -= a[i];
			pq.push(a[i]);
		}
		else if(pq.size() && pq.top() > a[i])// 注意堆为空时不能访问. 
		{
			money += (pq.top()-a[i]);
			pq.pop();
			pq.push(a[i]);
		}
		money += x;
	}
	cout << happy << '\n';
}

标签:pq,int,题解,void,Round946,cin,vector,func,div3
From: https://www.cnblogs.com/zerocloud01/p/18223332

相关文章

  • P2215 [HAOI2007] 上升序列题解
    题目大意对于一个集合$S$,对于$S$中长度为$m$的子序列$P$,在集合$P$中如果$P_1<P_2<...<P_m$那么我们称$P$为$S$的一个上升序列。如果有多个$P$满足条件我们就输出最小的那个,如果没有完成条件的$P$则输出Impossible。思路对于一个含有$......
  • P2266 爱的供养题解
    题目大意给你一个矩阵$w$,大小为$n\timesm$,然后你每次都从一个宝藏点开始去走旁边$T-1$个点施法,施法过的点就不用再走了,施法不需要耗费体力但是每一次从一个点走到另一个点需要耗费的权值为这两个点的高度差,你每次可以走的方向是上下左右。求最小需要耗费的体力。......
  • P10526 [XJTUPC2024] 命令行题解
    题目大意对于一个字符串$s$在输入的最后一行读入的字符,如个字符不为$E\(,\)T\(,\)B$那么这一个字符就添加至字符串$s$的末尾。对于操作$B$那么执行删除字符串$s$的最后一个字符,如果$s$为空那么跳过这个操作。对于操作$T$找到一个以字符串......
  • P10530 [XJTUPC2024] 生命游戏 题解
    题目大意一棵树一共$n$个点如果有$k$个点与某一个点相连那么这一轮的结尾这个点就会死。思路这道题有几个坑!并没有说哪一个节点是根节点。双向边记得开双倍数组。等这一轮的点消除完了才能再次判断哪一些点可以消除。首先我们创建一个数组$Size_{n}$来......
  • CF/505/D 题解
    思路这道题的思路其实是根据样例图片来的。首先第一张:这张图片可以得知$n$个点没有环的时候最少需要$n-1$个点。再看第二张:这个图确实很难思考,但稍微思考一下如果我们把含有一个强连通分量的图变成一整个强连通图。这个图的边数不就变成$n$了吗?来推一下......
  • P6342 [CCO2017] Vera 与道路建设 题解
    题目大意对于一个图w一共有v个点点的编号为1,2,...,v,对于点a与点b如果满足$a\tob$且$b\toa$使得每一条道路都只走过一次,那么我们称$a,b$为完美点对,当一个联通图只有$k$个完美点对时,称这个联通图为美丽公路网,要求求出一个美丽公路网......
  • Nikita and LCM题解
    题目大意给你一个数组$a$,令$t$为$a$的子序列且$t$中所有数的最小公倍数$\notina$求$t$数组中最多有多少个数。思路非常明显这是一道数学题,对于数组$a$我们首先从小到大拍一个序,然后我们可以求出$a$中所有数的最大公倍数,如果这个公倍数$\not=......
  • MITIT 2024 Spring Invitational Qualification 简要题解
    这个比赛没有找到题解,有点难绷,所以来写篇。(实际上是无聊时写的就是了)题面:https://codeforces.com/gym/105125/。目测难度是绿绿黄紫紫。A有点诈骗。其实策略是只保留\(\le3\)个数,然后就随便维护一下。\(O(n\logn)\)。Code#include<bits/stdc++.h>usingnamespaces......
  • Gym-100520A Andrew Stankevich Contest 45 A 题解
    AnalogousSetsGym-100520ASol1.集合生成函数将可重集合\(M\)映射为生成函数:\[F(M)=\sum_{m\inM}(\#m)\cdotx^m\]如果\(M\)的元素在\(\mathbbN\)上取值,那么,\(F(M)\)是多项式。2.\(\theta\)算子\[\theta(F)=x\cdotF'\]其中\(F'=\frac{dF}{dx}\)......
  • Springboot报class path resource [xxxxx.json] cannot be resolved to URL because i
    当Springboot解析resources文件下的json文件时,在本地环境好用,部署到服务器上找不到文件内容报错classpathresource[xxxxx.json]cannotberesolvedtoURLbecauseitdosenotexist问题排查(1)pom.xml文件配置<build><resources><resource><d......