CF1624C Division by Two and Permutation

原题链接

题意

t 组数据

每组给一个长度为 n 的序列 a . 可以对序列中的每个数做除以 2 操作(向下取整),问这个序列能否通过这种操作变成一个 1 - n 的排列。

思路

赛时有想到优先给能凑到的数个数少的数先凑,然后有一个错误思路是如果一个数本身就再 1- n 内那么就不动它…… 然后自以为学了点 stl ,就一顿乱写,结果是一个半小时都没弄出来。。。

正确思路是:通过枚举发现越大的数能凑到的数越少,因为每个数都可以凑到 1,越往上就越少。然后对于每个数,首先先使它除到小于等于 n ,然后再使它能凑除当前没有被凑出的且最大的数,然后就标记一下就可以了,然后还要注意边界条件,除以 2 时要大于 0 ,否则会死循环。

代码

#include <bits/stdc++.h> 
using namespace std;
int main()
{
	int t;
	cin >> t;
	while (t -- )
	{
		int n;
		cin >> n;
		int a[n + 10];
		for (int i = 1; i <= n ; i ++ )
		{
			cin >> a[i];
		}
		bool st[n + 10] = {0};
		//因为越大的数可以凑出的数就越少,所以尽量先凑出大的数,然后再往小的看 
		for (int i = 1; i <= n; i ++ )
		{
			int x = a[i];
			while (x > n) x /= 2;
			while (st[x] && x > 0) x /= 2;
			st[x] = 1;
		}
		int f = 1;
		for (int i= 1; i <= n; i ++ ) 
		{
			if (!st[i])
			{
				cout  << "NO" << endl;
				f = 0;
				break;
			}
		}
		if (f) cout << "YES" << endl;
	}
	return 0;
}

赛时乱七八糟的代码

//#include<bits/stdc++.h>
//using namespace std;
//const int N = 55;
int a[N];
//int main()
//{
//	int t; cin >> t;
//	while (t -- )
//	{
//		int n;
//		scanf("%d", &n);
//		map<int, int> st;
//		vector<int> a;
//		bool res = 0;
//	
//		for (int i = 1; i <= n; i ++ ) 
//		{
//			int x;
//			scanf("%d", &x);
//			if (x > n)
//			{
//				a.push_back(x);
//			}
//		
//			if (x <= n && st[x] == 1) 
//			{
//				res = 1;
//			}
//		
//			if (x <= n)
//			{
//				st[x] = 1;
//			}
//		}
//		if (res)
//		{
//			cout << "NO" << endl;
//			continue;
//		}
//		sort(a.begin(), a.end());
//		for (int i = 1; i <= n; i ++ )
//		{
//			if (!st[i])
//			{
//				int x = a[0];
//				while (1)
//				{
//					if (x == i)
//					{
//						a.erase(a.begin());
//						break;
//					}
//					if (x == 0)
//					{
//						res = 1;
//						break;
//					}
//					x /= 2;
//				}
//			}
//			if (res) break;
//		}
//		if (res) cout << "NO" << endl;
//		else cout << "YES" << endl;
//	}
//	return 0;
//}
#include<bits/stdc++.h>
using namespace std;
bool cmp(pair<int, int> a, pair<int, int> b)
{
	return a.second < b.second;
}
int main()
{
	int T;
	cin >> T;
	while (T -- )
	{
		int n;
		cin >> n;
		vector<int> a[55];
		map<int, int> f;
		map<int, int> num;
		pair<int, int> p[n + 10];
		int cnt = 0;
		for (int i = 1; i <= n; i ++ )
		{
			int x;
			cin >> x;
			int xx = x;
			num[x] ++;
			while (x > 0)
			{
				f[xx] ++;
				a[x].push_back(xx);
//				cout << x << " ";
				x /= 2;
			}
//			cout << endl;
		}
	
		map<int, int> stt;
		for (int i = 1; i <= n; i ++ )
		{
			p[i] = {i, f[i]};
		}
		sort(p + 1, p + 1 + n, cmp);
	
		bool ans = 0;
	
//		for (int i = 1; i <= n; i ++ ) cout << p[i].first << " " << p[i].second << endl;
	
//		for (int i = 1; i <= n; i ++ )
//		{
//			cout << i << " ::  ";
//			for (int j = 0; j < a[i].size(); j ++ )
//			{
//				cout << a[i][j] << " ";
//			}
//			cout << endl;
//		}
	
		for (int i = 1; i <= n; i ++ )
		{
			auto t = p[i];
		
//			if (f[t.first] == 0) //没有数可以凑成 
//			{
//				ans = 1;
//				break;
//			}
			bool ff = 0; //看有没有数可以用
		
			//尽量从小往大选 
//			sort(a[t.first].begin(), a[t.first].end());
			for (int j = 0; j < a[t.first].size(); j ++ )
			{
				//如果剩余个数大于0 
				if (num[a[t.first][j]] > 0)
				{
//					cout <<  a[t.first][j] << endl;
					num[a[t.first][j]] -- ;
					ff = 1;
					break;
				}
			}
			if (!ff)
			{
				ans = 1;
				break;
			}
		}
//		for (int i = 1; i <= n; i ++ )
//		{
//			cout << p[i].first << " " << p[i].second << endl;
//			if (p[i].second == 0)
//			{
//				ans = 1;
//				break;
//			}
//		
//			bool ff = 0;
//			for (int j = 0; j < a.size(); j ++ )
//			{
//				int x = a[j];
//				while (1)
//				{
//					if (x == i)
//					{
//						a.erase(a.begin() + j);
//						ff = 1;
//						break;
//					}
//					if (x == 0) break;
//					x /= 2;
//				}
//				if (ff) break;
//			
//			}
//			if (!ff) 
//			{
//				ans = 1;
//				break;
//			}
//		}
		if (ans ) cout << "NO" << endl;
		else cout << "YES" << endl;
	}
	return 0;
} 

//#include<bits/stdc++.h>
//using namespace std;
//const int N = 55;
int a[N];
//int main()
//{
//	int t; cin >> t;
//	while (t -- )
//	{
//		int n;
//		scanf("%d", &n);
//		map<int, int> st;
//		vector<int> a;
//		bool res = 0;
//	
//		for (int i = 1; i <= n; i ++ ) 
//		{
//			int x;
//			scanf("%d", &x);
//			if (x > n)
//			{
//				a.push_back(x);
//			}
//		
//			if (x <= n && st[x] == 1) 
//			{
//				res = 1;
//			}
//		
//			if (x <= n)
//			{
//				st[x] = 1;
//			}
//		}
//		if (res)
//		{
//			cout << "NO" << endl;
//			continue;
//		}
//		sort(a.begin(), a.end());
//		for (int i = 1; i <= n; i ++ )
//		{
//			if (!st[i])
//			{
//				int x = a[0];
//				while (1)
//				{
//					if (x == i)
//					{
//						a.erase(a.begin());
//						break;
//					}
//					if (x == 0)
//					{
//						res = 1;
//						break;
//					}
//					x /= 2;
//				}
//			}
//			if (res) break;
//		}
//		if (res) cout << "NO" << endl;
//		else cout << "YES" << endl;
//	}
//	return 0;
//}
//#include<bits/stdc++.h>
//#define int long long
//using namespace std;
//
//bool cmp(pair<int, int> a, pair<int, int> b)
//{
//	return a.second < b.second;
//}
//signed main()
//{
//	int T;
//	cin >> T;
//	while (T -- )
//	{
//		int n;
//		cin >> n;
//	
//		map<int, int> f;
//		map<int, int> num;
//		pair<int, int> p[n + 10];
//		int cnt = 0;
//		vector<int> a[10000008];
//		for (int i = 1; i <= n; i ++ )
//		{
//			int x;
//			cin >> x;
//			if (num[x] == 0) a[x].clear();
//			int xx = x;
//			num[x] ++;
//			while (x > 0)
//			{
//				f[x] ++;
//				a[x].push_back(xx);
				cout << x << " ";
//				x /= 2;
//			}
			cout << endl;
//		}
//	
//		map<int, int> stt;
//		for (int i = 1; i <= n; i ++ )
//		{
//			p[i] = {i, f[i]};
//		}
//		sort(p + 1, p + 1 + n, cmp);
//	
//		bool ans = 0;
//	
//		for (int i = 1; i <= n; i ++ ) 
//		{
			cout << p[i].first << " " << p[i].second << endl;
//			sort(a[i].begin(), a[i].end());
//		}
//	
		for (int i = 1; i <= n; i ++ )
		{
//			cout << i << " ::  ";
			for (int j = 0; j < a[i].size(); j ++ )
			{
				cout << a[i][j] << " ";
			}
			cout << endl;
		}
//	
//		for (int i = 1; i <= n; i ++ )
//		{
//			auto t = p[i];
//
//			bool ff = 0;
			cout << t.first<< "  :::   ";
//			for (int j = 0; j < a[t.first].size(); j ++ )
//			{
//				if (num[a[t.first][j]] > 0)
//				{
					cout << num[a[t.first][j]] << endl;
//					num[a[t.first][j]] -- ;
//					ff = 1;
//					break;
//				}
//			}
//			if (!ff)
//			{
//				ans = 1;
//				break;
//			}
//		}
//		if (ans ) cout << "NO" << endl;
//		else cout << "YES" << endl;
//	}
//	return 0;
//} 
#include<bits/stdc++.h>
using namespace std;
int main()
{
	int t; cin >> t;
	while (t -- )
	{
		int n;
		cin >> n;
		int a[n + 10];
		int k[n + 10];
		for (int i = 1; i <= n; i ++ )
		{
			cin >> a[i];
		}
		for (int )
	}
	return 0;
}

总结

我也不懂,这种题目,总是想不出来。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值