坐大牢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;
}