The 3rd Universal Cup. Stage 7: Warsaw(VP)

坐大牢F,T-T
B. Missing Boundaries

题目链接:Missing Boundaries - Problem - QOJ.ac

题意:

给你n个区间[l,r],-1代表可以为任意值(保证l<=r),问是否可以让n个区间覆盖1-m且区间之间没有重叠。

思路:

我们发现【-1,-1】是万能区间,所以我们将其单独拿出来计数。接着我们可以将剩下的区间先按x排序,如果x为-1,按y排序。(我这是将x为-1的单独拿出来,然后归并排序,实际结果一样)

接着就是大模拟,看看是否所有的万能区间能填进去,是否能对1-m全覆盖以及是否有重叠部分。

代码:

#include<bits/stdc++.h>
using namespace std;

#define ull unsigned long long
#define ll long long
#define edl '\n'

const int N = 1e6 + 10;
const int M = 1e3 + 10;

const int mod = 1e9 + 7;
ll n,m,q;
string s;

struct QWQ
{
	ll x,y;
}a[N],c[N],ans[N];

bool cmp(QWQ A,QWQ B)
{
	return A.x < B.x;
}

bool cmp2(QWQ A,QWQ B)
{
	return A.y < B.y;
}

void solve()
{
	ll sum = 0;
	ll la,lc,lans;
	la = lc = lans = 0;
	cin >> n >> m;
	for(int i = 1; i <= n; i ++ )
	{
		ll l,r;
		cin >> l >> r;
		if(l == -1 && r == -1) sum ++;
		else if(l == -1) a[++la] = {l,r};
		else c[++lc] = {l,r};
	}
	sort(c + 1, c + lc + 1,cmp);
	sort(a + 1, a + la + 1,cmp2);
	int i = 1;
	int j = 1;
	while(j <= lc)
	{
		while(i <= la && a[i].y <= c[j].x)
		{
			ans[++lans] = a[i];
			i ++;
		}
		ans[++lans] = c[j];
		++j;
	}
	while(i <= la)
	{
		ans[++lans] = a[i];
		++i;
	}
	ans[++lans] = {m + 1,m + 1};
	ans[lans + 1] = {m + 2,m + 2};
	ll kk = 0;
	for(int i = 1; i <= lans; i ++ )
	{
		if(ans[i].x == -1)
		{
			ans[i].x = ans[i - 1].y + 1;
			kk += ans[i].y - ans[i].x;
		}
		if(ans[i].y == -1)
		{
			if(ans[i + 1].x != -1)
			{
				ans[i].y = ans[i + 1].x - 1;
			}
			else
			{
				ans[i].y = ans[i + 1].y - 1;
				ans[i + 1].x = ans[i + 1].y;
			}
			kk += ans[i].y - ans[i].x;
		}
	}
	for(int i = 1; i <= lans; i ++ )
	{
		if(ans[i].x <= ans[i].y) continue;
		else
		{
			cout << "NIE" << edl;
			return;
		}
	}
	for(int i = 1; i <= lans; i ++ )
	{
		if(ans[i].x > ans[i - 1].y + 1)
		{
			sum --;
			kk += ans[i].x - ans[i - 1].y - 2;
		}
		else if(ans[i].x == ans[i - 1].y + 1) continue;
		else
		{
			cout << "NIE" << edl;
			return;
		}
	}
	if(sum <= kk && sum >= 0) cout << "TAK" << edl;
	else cout << "NIE" << edl;
}

int main()
{
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	int t = 1;
	cin >> t;
	while(t -- ) solve();
	return 0;
}
L. Random Numbers

题目链接:Random Numbers - Problem - QOJ.ac

思路:

这是一道很有意思的题,我们注意到他数据是随机的,所以我们可以算期望,每个数的期望是n/2,因此区间之和为长度平方的期望长度因该就是n/2,我们直接暴力枚举长度为【n/2 - 500,n/2+500】即可,保险起见长度为2-200的也枚举一下。

代码:

#include<bits/stdc++.h>
using namespace std;

#define ull unsigned long long
#define ll long long
#define edl '\n'

const int N = 1e6 + 10;
const int M = 1e3 + 10;

const int mod = 1e9 + 7;
ll n,m,q;
string s;

ll a[N];
ll sum[N];

void solve()
{
	cin >> n;
	for(int i = 1; i <= n; i ++ )
	{
		cin >> a[i];
		sum[i] = sum[i - 1] + a[i];
	}
	ll ans = 1;
	ll ok = (n + 1) / 2;
	ll op = min(200LL,n);
	for(ll i = 2; i <= op; i ++ )
	{
		for(int j = 1; j + i - 1 <= n; j ++ )
		{
			if(sum[j + i - 1] - sum[j - 1] == i * i) ans ++;
		}
	}
	for(ll i = max(op + 1,ok - 500); i <= min(n,ok + 500); i ++ )
	{
		for(int j = 1; j + i - 1 <= n; j ++ )
		{
			if(sum[j + i - 1] - sum[j - 1] == i * i) ans ++;
		}
	}
	cout << ans << edl;
}

int main()
{
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	int t = 1;
	cin >> t;
	while(t -- ) solve();
	return 0;
}
D. Data Determination

 题目链接:Data Determination - Problem - QOJ.ac

判断中位数

二分即可

#include <bits/stdc++.h>
using namespace std;

#define ull unsigned long long
#define ll long long
#define edl '\n'
const int N = 2e5 + 10;
const int M = 1e3 + 10;

const int mod = 1e9 + 7;
ll n, m, q;
string s;

ll a[N];

void solve()
{
	ll n, k, m;
	cin >> n >> k >> m;
	for (ll i = 1; i <= n; i++)cin >> a[i];
	sort(a + 1, a + 1 + n);
	auto check = [&](ll x)
	{
		ll l = 1, r = n;
		while (l <= r)
		{
			ll mid = l + r >> 1;
			if (a[mid] >= x)r = mid - 1;
			else l = mid + 1;
		}
		return l;
	};
	ll flag = 0;
	if (k & 1)
	{
		for (ll i = 1; i <= n; i++)
		{
			if (a[i] == m)
			{
				if (i - 1 >= (k - 1) / 2 && n - i >= (k - 1) / 2)flag = 1;
			}
		}

	}
	else
	{
		for (ll i = 1; i <= n; i++)
		{
			ll res = 2 * m - a[i];
			ll pos = check(res);
			if (i >= pos)pos = i + 1;
			if (pos <= n && a[pos] == res && i - 1 >= (k - 2) / 2 && n - pos >= (k - 2) / 2)
			{
				flag = 1;
			}
		}
	}
	if (flag)cout << "TAK" << edl;
	else cout << "NIE" << edl;
}

int main()
{
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	ll t = 1;
	cin >> t;
	while (t -- ) solve();
}
G. Game of Geniuses

题目链接 :Game of Geniuses - Problem - QOJ.ac

博弈,先后手划行列,先手划行留大,后手划列留小。

假设先手最后留下第i行,那么后手会让其最小,即答案为每一行最小值的最大。

代码:

#include<bits/stdc++.h>
using namespace std;

#define ull unsigned long long
#define ll long long
#define edl '\n'

const int N = 1e7 + 10;
const int M = 1e3 + 10;

const int mod = 1e9 + 7;
ll n,m,q;
string s;

ll a[N];

bool cmp(ll A,ll B)
{
	return A > B;
}

void solve()
{
	int n;cin>>n;
	int ans=0;
	for(int i=1;i<=n;i++){
		int mn=3000;
		for(int j=1;j<=n;j++){
			int x;cin>>x;
			mn=min(mn,x);
		}
		ans=max(ans,mn);
	}
	cout<<ans;
}

int main()
{
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	int t = 1;
//	cin >> t;
	while(t -- ) solve();
	return 0;
}
M. Mathematics Championships

题目链接 :Mathematics Championships - Problem - QOJ.ac

思路:

每一个人出局时他所代表的分数为2^i个人分数之和。

问所有人出局时分数最大,那就是最大的2^i个人分数之和加起来,枚举i取max

代码:

#include<bits/stdc++.h>
using namespace std;

#define ull unsigned long long
#define ll long long
#define edl '\n'

const int N = 1e7 + 10;
const int M = 1e3 + 10;

const int mod = 1e9 + 7;
ll n,m,q;
string s;

ll a[N];

bool cmp(ll A,ll B)
{
	return A > B;
}

void solve()
{
	cin >> n;
	for(int i = 1; i <= (1LL << n); i ++ ) cin >> a[i];
	sort(a + 1, a + (1LL << n) + 1,cmp);
	ll ans = a[1];
	ll ok = 1;
	for(int i = 1; i <= (1LL << n); i ++ )
	{
		a[i] += a[i - 1];
		if(i == ok)
		{
			ans = max(a[i],ans);
			ok *= 2;
		}
	}
	cout << ans << edl;
}

int main()
{
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	int t = 1;
//	cin >> t;
	while(t -- ) solve();
	return 0;
}
J. Juliet Unifies Ones

 题目链接 :Juliet Unifies Ones - Problem - QOJ.ac

暴力枚举中间为1-l全0,r-n全0的两个边界,中间全0或全1取min

代码:

#include<bits/stdc++.h>
using namespace std;

#define ull unsigned long long
#define ll long long
#define edl '\n'

const int N = 1e6 + 10;
const int M = 1e3 + 10;

const int mod = 1e9 + 7;
ll n,m,q;
string s;


void solve()
{
	ll ans = LLONG_MAX;
	cin >> s;
	for(int i = 0; i < (int)s.length(); i ++ )
	{
		for(int j = i; j < (int)s.length(); j ++ )
		{
			ll sum1 = 0;
			ll sum = 0;
			for(int ii = i; ii <= j; ii ++ )
			{
				if(s[ii] == '1') sum1 ++;
				else sum ++;
			}
			ll g = 0;
			for(int ii = 0; ii < i; ii ++ )
			{
				if(s[ii] == '1') g ++;
			}
			for(int ii = j + 1; ii < (int)s.length(); ii ++ )
			{
				if(s[ii] == '1') g ++;
			}
			ans = min(ans,g + min(sum1,sum));
		}
	}
	cout << ans << edl;
}

int main()
{
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	int t = 1;
//	cin >> t;
	while(t -- ) solve();
	return 0;
}
  • 5
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值