Codeforces Round #812 (Div. 2)

这次cf打的额,是菜中菜


A - Traveling Salesman Problem

  • 思路:
    最短路径在y轴上面走的步数是 (ymax - ymin ) * 2 (ymax是y >= 0的最大值,ymin是y <= 0的最小值,来回乘2,)同理在x轴上面走的步数是(xmax - xmin ) * 2 ,所以一共走 (ymax - ymin ) * 2 + (xmax - xmin ) * 2
  • 代码:
#include <bits/stdc++.h>
#define int long long 
#define ios ios::sync_with_stdio(0),cin.tie(0)
#define fi first
#define se second
#define pb push_back
#define PII pair<int,int>
using namespace std;

const int N = 2e5 + 100,M = N * 2,INF = 0x3f3f3f3f;

void solve()
{
   int n; cin >> n;
   int xmin = 0,xmax = 0,ymin = 0,ymax = 0;
   
   for(int i = 1;i <= n;i ++ )
   {
   	int x,y; cin >> x >> y;
   	if(x == 0)
   	{
   		if(y >= 0)
   		ymax = max(ymax,y);
   		else
   		ymin = min(ymin,y);
	}
	else if(y == 0)
	{
		if(x > 0)
		xmax = max(xmax,x);
		else
		xmin = min(xmin,x);
	}
	
   }
   int u = (ymax - ymin) * 2 + (xmax - xmin) * 2;
   cout << u << endl; 
   
}

signed main()
{
    ios;int T; cin >> T; while(T -- ) solve();
    return 0;
}

B - Optimal Reduction

  • 思路:

你最终发现,最优先的路径一定是先递增后递减的,直接模拟

#include <bits/stdc++.h>
#define int long long 
#define ios ios::sync_with_stdio(0),cin.tie(0)
#define fi first
#define se second
#define pb push_back
#define PII pair<int,int>
using namespace std;

const int N = 2e5 + 100,M = N * 2,INF = 0x3f3f3f3f;
int a[N],b[N];

void solve()
{
 int n; cin >> n;
 for(int i = 1;i <= n;i ++ ) cin >> a[i];
 int id = 0;
 for(int i = 1;i <= n - 1;i ++ )
 {
 	if(a[i] <= a[i + 1]) continue;
 	else
 	{
 		id = i;
 		break;
	 }
 }
 
 if(id == 0) cout << "YES" << endl;
 else
 {
 	for(int i = id;i <= n - 1;i ++ )
 	{
 		if(a[i] < a[i + 1])
 		{
 			cout << "NO" << endl;
 			return;
		 }
	}
	
	cout << "YES" << endl;
 }
	
	
}

signed main()
{
    ios;int T; cin >> T; while(T -- ) solve();
    return 0;
}

C - Build Permutation

  • 思路:

因为n的范围在1e5之内,所以x最多取 s q r t ( 1 e 5 ) sqrt(1e5) sqrt(1e5),不超过400,所以直接硬暴力就行,因为 i + a[i] = x * x,下标为(x * x - i)的也就找到了,那当下标为 i 的也就找到了,比如 3 + 6 = 9,a[6] = 3,那a[3] = 6,从后往前就行

  • 代码:
#include <bits/stdc++.h>
#define int long long 
#define ios ios::sync_with_stdio(0),cin.tie(0)
#define fi first
#define se second
#define pb push_back
#define PII pair<int,int>
using namespace std;

const int N = 2e5 + 100,M = N * 2,INF = 0x3f3f3f3f;
int a[N],b[N];
int ans[N];
bool st[N];
void solve()
{
	int n; cin >> n;
	memset(st,false,sizeof st);
	
	for(int i = n - 1;i >= 0;i -- )
	{
		int f = 0;
		if(st[i])continue;
		
		
		if(!st[i])
		{
					for(int j = 400;j >= 0;j -- )
		{
			if(j * j - i >= 0 && j *j - i <= n - 1)  
			{
				if(!st[j * j - i] && !st[i])
				{
					st[j * j - i] = true;
					st[i] = true;
					ans[j * j - i] = i;
					ans[i] = j * j - i;
					f = 1;
					break;
				}
			}
		}
		}

		
		if(f == 0)
		{
			cout << "-1" << endl;
			return;
		}
		
	}
	
	for(int i = 0;i <= n - 1;i ++ ) cout << ans[i] << ' ';
	cout << endl;
	
}

signed main()
{
    ios;int T; cin >> T; while(T -- ) solve();
    return 0;
}

D - Tournament Countdown

  • 思路:
    限定了询问次数,比如n = 2,那就最多两次询问,那看如何在两次询问中找到冠军,我们首先可以知道,n = 2,只有三场比赛,那4个数字里面,一定有两个人的胜场是0,且一个分布在[1,2]一个分部在[2,4],一定有一个人的胜场是2,另一个人的胜场是1,那我们首先比较1 和 3,如果1 == 3,代表胜者肯定是在2和4里面产生的,如果1 > 3 那2,3一定不是冠军,那冠军一定在1 和 3产生,同理如果1 < 3 ,那1,4一定不是冠军,那冠军一定在2 和 3产生,这样只需要两次,同理从5 到 8 也是一样… 等等都是这样,模拟即可
  • 代码:
#include <bits/stdc++.h>
using namespace std;

const int N = 150000,M = N * 2,INF = 0x3f3f3f3f;
int a[N];
int ask(int c,int b)
{
	cout << "? " << c << " " << b << endl;
	int k;
	cin >> k;
	return k;
}

void query(int n)
{
	int s = 1;
	int qq = 1;
	int u = pow(2,n);
	while(s < u)
	{
		 int k = ask(a[s],a[s + 2]);
		 if(k == 0)
		 {
		 	int k1 = ask(a[s + 1],a[s + 3]);
		 	if(k1 == 1)
		 	a[qq] = a[s + 1];
		 	else
		 	a[qq] = a[s + 3]; 

		 }
		 else if(k == 1)
		 {
		 	int k1 = ask(a[s],a[s + 3]);
		 	if(k1 == 1)
		 	a[qq] = a[s];
		 	else
		 	a[qq] = a[s + 3];

		 }
		 else
		 {
		 	int k1 = ask(a[s + 2],a[s + 1]);
		 	if(k1 == 1)
		 	a[qq] = a[s + 2];
		 	else
		 	a[qq] = a[s + 1]; 	
		 }
		 
		 s += 4;
		 qq ++;
	}
	
	
}

 
void solve()
{
	int n;
	cin >> n; // 先两次确定一个胜者,两次确定一个胜者
	int u = pow(2,n);
	for(int i = 1;i <= u;i ++ ) a[i] = i;
	
	while(n > 0)
	{
		if(n == 1)
	{
		int k = ask(a[1],a[2]);
		if(k == 1) cout << "! " << a[1] << endl;
		else cout << "! " << a[2] << endl;
		return; 
	}
	
	query(n);
	n -= 2;
	
	if(n == 0)
	{
		cout << "! " << a[1] << endl;
	}
	
	}
}

int main()
{
	int T; cin >> T; while(T -- ) solve();
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值