Codeforces Round 1115 ( Div. 2)

Codeforces Round 1115 ( Div. 2)

引言

有人穷极一生所追求得,或许是有人一出生就有的,你能做的只能在你的小小领域中一步步蠕动。最终或许无法达到飞升之门!


上言纯纯废话,当成发屁。我们进入正题

题目链接:Dashboard - Codeforces Round 1115 (Div. 2) - Codeforces

话说这次怎么都是贪心啊


A题

题目入口:Problem - A - Codeforces

You are fighting a boss with an unknown amount of health. You have a sequence of n spell cards, where the i-th card deals ai damage. You can rearrange your hand and play the cards in any order you choose.

The boss has an adaptive shield. If you ever play two cards in a row that deal the exact same amount of damage, the shield permanently activates. The card that triggers the shield still deals its normal damage, but all subsequent cards you play will deal 0 damage.

Find the maximum total health the boss can have such that you will defeat him if you arrange and play your cards optimally.

Input

Each test contains multiple test cases. The first line contains the number of test cases t (1≤t≤100). The description of the test cases follows.

The first line of each test case contains a single integer n (1≤n≤50) --- the number of spell cards.

The second line of each test case contains n integers a1,a2,...,an (1≤ai≤1000) --- the damage dealt by each card.

Output

For each test case, output a single integer --- the maximum total health the boss can have such that you will defeat him.

Example

Input

cpp 复制代码
4
1
100
4
10 5 10 10
5
1 2 3 4 5
6
7 7 7 7 7 7

Output

cpp 复制代码
100
35
15
14

思路:简直了,一个简单的A题800分就来了一个贪心,这真是进了贪心窝里了。

这题我们想想要伤害打的多,那么我们就肯定得交替着打,那么我们想是不是只有最多出现的那个可能会打不完?什么时候会打不完呢?那么我们想要是i出现最多的那个很多,我们尽可能的想多打伤害是不是先让这个出现最多的先打,那么我们就会起步多打了一个伤害,那么最终以这个出现最多的最后打一下结尾,那么我们整体是不是多打了两次?那就很明显了,我们统计出现最多的次数,然后和剩下的所有次数进行比较,我们记作做多的这个是ans次,剩下的次数是m次,如果ans-2>m,那么我们的最多次数就只能打ans-2次,剩下的可以打完。那要是ans-2<=m,那么这时候我们就可以把所有的打完了。这题贪心思路就结束了

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define int long long
#define endl '\n'
#define pii pair<int,int>
#define fi first
#define se second
#define YES cout<<"YES"<<endl
#define NO cout<<"NO"<<endl

void solve()
{
	int n;
	cin>>n;
	// vector<int> a(n);
	map<int,int> mp;
	for(int i=0;i<n;i++)
	{
		int num;
		cin>>num;
		mp[num]++;
	}
	if(mp.size()==1){
		int sum=0;
		for(auto x:mp){
			if(x.se==1) sum+=x.fi;
			else sum+=x.fi*2;
		}
		cout<<sum<<endl;
		return;
	}
	int ans=0;
	int mx=0,mxx=0;
	for(auto x:mp)
	{
		if(x.se>mx){
			mx=x.se;
			mxx=x.fi;
		}
	}
	for(auto x:mp){
		if(x.fi!=mxx) ans+=x.se;
	}
	if(ans>=mx-2){
		int sum=0;
		for(auto x:mp){
			sum+=(x.fi*x.se);
		}
		cout<<sum<<endl;
	}else{
		mp[mxx]=ans+2;
		int sum=0;
		for(auto x:mp){
			// if(x.fi==mxx) sum+=2*x.fi;
			// else 
			sum+=(x.fi*x.se);
		}
		cout<<sum<<endl;
	}
//	cout<<fixed<<setprecision(x)
}
signed main()
{
	IOS;
	int _=1;
	cin>>_;
	while(_--)
	solve();
	return 0;
}

B题

题目入口:Problem - B - Codeforces

You are given a binary string s of length n.

A string is called alternating if no two adjacent characters are the same. For example, 0101, 1, and 01 are alternating, but 0110 is not.

You want to transform s into an alternating string by performing the following operation any number of times (possibly zero):

  • Choose any character currently in the string and delete it.

However, your sequence of operations must follow a rule: the characters you delete must strictly alternate. This means if the last character you deleted was 0, the next character you delete must be 1, and vice versa. Your very first deleted character can be either 0 or 1.

Find the minimum number of operations required to make s an alternating string. If it is impossible to achieve this, output −1.

Input

Each test contains multiple test cases. The first line contains the number of test cases t (1≤t≤104). The description of the test cases follows.

The first line of each test case contains a single integer n (1≤n≤2⋅105) --- the length of the string s.

The second line of each test case contains the binary string s of length n, consisting only of the characters 0 and 1.

It is guaranteed that the sum of n over all test cases does not exceed 2⋅105.

Output

For each test case, output a single integer --- the minimum number of operations required to make s an alternating string, or −1 if it is impossible.

Example

Input

cpp 复制代码
5
4
0101
3
111
6
100110
6
100010
6
011110

Output

cpp 复制代码
0
-1
2
3
5

思路:这个题目还是一个纯贪心问题啊,我们想要尽可能少的次数删除之后到达一个交替串,那莪就是要一个尽可能长的交替串,那么我们就把这个串尽可能先找出来。我们先把这个最长的串找出来,也就是说从串的第一个字符开始找,要是他是0就从0开始找,要是他是1就从1开始找,然后我们交替找最长串,然后找到最长串之后我们的答案肯定在最长串和最长串-1两个之间啊,因为如果第一个是0但是我们最后能达到的交替最长串Kennedy个开头是1得把这个0删除了。

然后我们还得i知道一个数学思维的知识吧,就是要是最终的串第一个字符是1,那么要是串长度是奇数,那么应该这个串的cnt1-cnt0=1,然后要是偶数那么就应该cnt1==cnt0,反之一样。我们只要判断合不合法这个条件,最终我们取一个最长度最长值,也就是删除最少值。最后看看ans变化了没有,没有变化那就是两种情况都不符合,直接输出-1,其他符合的输出ans就行了。

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define int long long
#define endl '\n'
#define pii pair<int,int>
#define fi first
#define se second
#define YES cout<<"YES"<<endl
#define NO cout<<"NO"<<endl

void solve()
{
	int n;
    string s;
    cin>>n>>s;
    int cnt0=0,cnt1=0;
    for (int i=0;i<n;i++){
     	if(s[i]=='0')  cnt0++;
     	else cnt1++;
	}
    int ans=LLONG_MAX;
    for (int c=0;c<=1;c++)  
    {
        char ch='0'+c;
        int maxnum=0;
        for (int i=0;i<n;i++)
        {
            if (s[i]==ch)
            {
                maxnum++;
                if(ch=='0') ch='1';
                else ch='0';
            }
        }
        int an=max(maxnum-1,0LL);
        for (int i=maxnum;i>=an;i--)
        {
            int k0,k1;
            if (c==0){
            	k0=(i+1)/2;
            	k1=i/2;
            }
            else{
            	k1=(i+1)/2;
            	k0=i/2;
            }
            if(k0>cnt0||k1>cnt1) continue;
            int shu0=cnt0-k0;
            int shu1=cnt1-k1;
            if (abs(shu0-shu1)<=1)
                ans=min(ans,n-i); 
        }
    }
    if(ans==LLONG_MAX) ans=-1;
    cout<<ans<<endl;
}

signed main()
{
	IOS;
	int _=1;
	cin>>_;   
	while(_--)
	solve();
	return 0;
}

C题

题目入口:Problem - C - Codeforces

You are playing a 2D Jenga game represented by a grid with n rows and m columns. The 1-st row is the top level of the tower, and the n-th row is the bottom level.

Each piece at row i and column j has a destabilization factor ai,j. Additionally, each row i has an initial stability index of vi.

When you remove a piece, it is completely discarded from the game. Removing a piece from row i damages all levels at and above it. Specifically, for every row k such that 1≤k≤i, its stability index is decreased by ai,j.

The tower collapses if either of the following conditions is met:

  • The stability index of any level drops to 0 or less.
  • Any level is left with exactly 0 pieces (even if it is the topmost level).

Find the minimum number of pieces you must remove such that the tower collapses.



Input

Each test contains multiple test cases. The first line contains the number of test cases t (1≤t≤104). The description of the test cases follows.

The first line of each test case contains two integers n and m (1≤n,m≤106) --- the number of rows and columns of the tower.

The second line contains n integers v1,v2,...,vn (1≤vi≤109) --- the initial stability indices of each level from top to bottom.

Each of the next n lines contains m integers. The j-th integer on the i-th line is ai,j (1≤ai,j≤109) --- the destabilization factor of the piece at row i and column j.

It is guaranteed that the sum of n⋅m over all test cases does not exceed 106.

Output

For each test case, output a single integer --- the minimum number of pieces that must be removed to collapse the tower.

Example

Example

Input

cpp 复制代码
2
2 3
10 20
2 2 2
5 5 5
3 1
100 100 100
1
2
3

Output

cpp 复制代码
2
1

思路:这题还是一个贪心题啊,有两条路可以走,要么就是拿走一层的所有积木,也就是打底是m次就可以,然后在m的基础上看看能不能在少点积木可以破坏。那么我们想,题目说了下面的楼层木块能够影响上面所有楼层的,那么我们就可以从下面往上面遍历啊,因为从上往下遍历的话没法普及完整啊。那么由于我们想尽可能快的破坏,那么我们肯定是集中一个区域进行破坏,而且由于下楼层能影响上面的楼层,那么我们就可能把每层的楼层以及它上面的楼层的最小保护值存起来,也就是用到了前缀最小的方法啊。然后我们用一个大根堆从大到小存这个木块(当然了一层一层的存),从最底部开始遍历,然后我们的目标是在ans块之内能不能把这层的目标达到,(下面的楼层能够帮忙,所以我们把下面大的数也存进来了)。然后我们一边更新ans,一遍尝试还能不能再少一点木块能够破坏,左后遍历到最高层,遍历结束这时候的ans就是最少块数。

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define endl '\n'
#define int long long
#define pii pair<int,int>
#define fi first
#define se second
#define YES cout<<"YES"<<endl;
#define NO cout<<"NO"<<endl;

const int INF=1e6+5;
void solve()
{
	int n,m;
	cin>>n>>m;
	vector<int> v(n+1);
	for(int i=1;i<=n;i++) cin>>v[i];
	vector<int> mi(n+1);
	mi[1]=v[1];
	for(int i=2;i<=n;i++) {
		mi[i]=min(mi[i-1],v[i]);
	}
	vector<vector<int>> a(n+1,vector<int>(m+1));
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			cin>>a[i][j];
	int ans=m;
	priority_queue<int> q;
	vector<int> need;
	for(int i=n;i>=1;--i)
	{
		for(int j=1;j<=m;j++)
		{
			q.push(a[i][j]);
		}
		int sum=0;
		// vector<int> need;
		for(int j=1;j<=ans;j++)
		{
			int x=q.top();
			q.pop();
			need.push_back(x);
			sum+=x;
			if(sum>=mi[i]){
				ans=j;
				break;
			}
		}
		int len=need.size();
		for(int j=0;j<len;j++){
			q.push(need[j]);
		}
		need.clear();
	}
	cout<<ans<<endl;
	// cout<<fixed<<setprecision(x)<<
}
signed main()
{
	IOS;
	int _=1;
	cin>>_;
	while(_--)
	solve();
	return 0;
}

总结

本周的Div2也是震惊我了,全是贪心,估计难度不超过1200,可惜的是我赛时C是从上到下遍历的,所以我差了点情况,要当时想到了从下到上走的想法就好了!

还有两场,努力吧!

相关推荐
计算机小白一个1 小时前
蓝桥杯 Java B 组之哈希表应用(两数之和、重复元素判断)
java·数据结构·算法·蓝桥杯
Loge编程生活1 小时前
打卡信奥刷题(3449)用C++实现信奥题 P10429 [蓝桥杯 2024 省 B] 拔河
开发语言·数据结构·c++·算法·青少年编程
2601_957174652 小时前
大模型算法 简单 容易 用这个方法
算法
VALENIAN瓦伦尼安教学设备2 小时前
激光对中仪采购要点
数据库·嵌入式硬件·算法
lilili也4 小时前
visual studio add matlab
c语言·c++
沫璃染墨4 小时前
《Qt从零入门系列(一):Qt框架初识——从发展历史到跨平台开发》
c++·qt·系统架构·gui
Forever Nore4 小时前
LeetCode 1 两数之和
算法·leetcode·职场和发展
To_OC4 小时前
LC 3 无重复字符的最长子串:从入门滑动窗口到优化写法,再也不怕面试官追问
javascript·算法·leetcode
(Charon)5 小时前
【C++】多线程死锁:产生原因、复现与解决方法
开发语言·c++·算法