补一下牛客,菜得发昏了,F搞了两个小时都没搞出来,不如去开H了
还没补完 剩下的打了atc再来
文章目录
- 牛客 寒假集训1A DFS搜索
- 牛客 寒假集训1B 关鸡
- 牛客 寒假集训1C 按闹分配
- 牛客 寒假集训1D 数组成鸡
- 牛客 寒假集训1E 本题又主要考察了贪心
- 牛客 寒假集训1G why买外卖
- 牛客 寒假集训1H 01背包,但是bit
牛客 寒假集训1A DFS搜索
题目链接
看数据很小于是纯暴力解法
#include <bits/stdc++.h>
using namespace std;
#define int long long
using i64 = long long;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
const int N = 1000010;
void solve()
{
int n;
cin >> n;
string s;
cin >> s;
bool flag1 = false, flag2 = false;
for (int i = 0; i < n; i ++ )
{
if (s[i] == 'd')
{
for (int j = i + 1; j < n; j ++ )
{
if (s[j] == 'f')
{
for (int k = j + 1; k < n; k ++ )
{
if (s[k] == 's')
{
flag1 = true;
break;
}
}
if (flag1) break;
}
}
if (flag1) break;
}
}
for (int i = 0; i < n; i ++ )
{
if (s[i] == 'D')
{
for (int j = i + 1; j < n; j ++ )
{
if (s[j] == 'F')
{
for (int k = j + 1; k < n; k ++ )
{
if (s[k] == 'S')
{
flag2 = true;
break;
}
}
if (flag2) break;
}
}
if (flag2) break;
}
}
if (flag2) cout << 1 << ' ';
else cout << 0 << ' ';
if (flag1) cout << 1 << '\n';
else cout << 0 << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t -- )
{
solve();
}
}
牛客 寒假集训1B 关鸡
题目链接
我是分两种讨论,从左边出去和从右边出去,先把坐标按y从小到大排序,遍历每一个坐标,看下一个坐标是不是在当前坐标的下面或者右下面或者右上面,是的话当前这一端就封死了
答案最大是3(在鸡的左右下)
#include <bits/stdc++.h>
using namespace std;
#define int long long
using i64 = long long;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
const int N = 1000010;
bool cmp(PII a, PII b)
{
if (a.second != b.second) return a.second < b.second;
else return a.first < b.first;
}
void solve()
{
int n;
cin >> n;
vector<PII> pos(n);
int cnt = 0;
for (int i = 0; i < n; i ++ )
{
cin >> pos[i].first >> pos[i].second;
if (pos[i].first == 1 && pos[i].second == -1) cnt ++ ;
if (pos[i].first == 1 && pos[i].second == 1) cnt ++ ;
if (pos[i].first == 2 && pos[i].second == 0) cnt ++ ;
}
sort(pos.begin(), pos.end(), cmp);
if (n == 0)
{
cout << 3 << '\n';
return;
}
if (cnt == 3)
{
cout << 0 << '\n';
return;
}
bool flag1 = false, flag2 = false;
for (int i = 0; i < n - 1; i ++ )
{
int x = pos[i].first, y = pos[i].second;
if (y < 0)
{
if (flag1) continue;
if (x == 1)
{
if (pos[i + 1].first == 2 && (pos[i + 1].second == y || pos[i + 1].second == y + 1)) flag1 = true;
}
else
{
if (pos[i + 1].first == 1 && pos[i + 1].second == y + 1) flag1 = true;
}
}
else
{
if (flag2) break;
if (x == 1)
{
if (pos[i + 1].first == 2 && (pos[i + 1].second == y || pos[i + 1].second == y + 1)) flag2 = true;
}
else
{
if (pos[i + 1].first == 1 && pos[i + 1].second == y + 1) flag2 = true;
}
}
}
if (flag1 && flag2) cout << 0 << '\n';
else if (flag1)
{
int x = pos[n - 1].first, y = pos[n - 1].second;
if (y >= 0) cout << 1 << '\n';
else cout << 2 << '\n';
}
else if (flag2)
{
int x = pos[0].first, y = pos[0].second;
if (y <= 0) cout << 1 << '\n';
else cout << 2 << '\n';
}
else
{
int ans = 0;
int x1 = pos[0].first, y1 = pos[0].second;
int x2 = pos[n - 1].first, y2 = pos[n - 1].second;
if (y1 <= 0) ans ++ ;
else ans += 2;
if (y2 >= 0) ans ++ ;
else ans += 2;
ans = min((i64)3, min(ans, 3 - cnt));
cout << ans << '\n';
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t -- )
{
solve();
}
}
牛客 寒假集训1C 按闹分配
题目链接
不知道为啥赛时脑抽写二分,实际上 O ( n ) O(n) O(n) 处理一下前缀和就搞定了
鸡插到某一个人前面,那增加的不满意度就是 t c t_c tc 乘上在鸡后面的人数,根据这个就能算出鸡最优能站在第几个人前面,剩下的前缀和就搞定了
下面代码还是二分,懒得写qaq
#include <bits/stdc++.h>
using namespace std;
#define int long long
using i64 = long long;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
const int N = 1000010;
void solve()
{
int n, q, c;
cin >> n >> q >> c;
vector<int> t(n + 1), pre(n + 1), tmp(n + 2);
for (int i = 1; i <= n; i ++ ) cin >> t[i], pre[i] = pre[i - 1] + t[i];
for (int i = 1; i <= n; i ++ ) pre[i] = pre[i - 1] + pre[i];
sort(t.begin(), t.end());
for (int i = 1; i <= n + 1; i ++ ) tmp[i] = tmp[i - 1] + t[i - 1];
while (q -- )
{
int m;
cin >> m;
auto check = [&](int mid)
{
int pos = upper_bound(tmp.begin(), tmp.end(), mid) - tmp.begin() - 1;
int time = pre[n] + (n - pos + 1) * c;
if (time - pre[n] > m) return false;
else return true;
};
int l = 0, r = pre[n];
while (l < r)
{
int mid = l + r >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
}
cout << r + c << '\n';
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
// cin >> t;
while (t -- )
{
solve();
}
}
牛客 寒假集训1D 数组成鸡
题目链接
这题又可以学到一个trick,m的范围在1e9之内,但是30个2相乘就已经超过了,所以n给那么大完全是吓唬人的,如果n很大,那只能说明有很多一样的数要变成1 or -1,所以枚举每一个数变成-1开始到更小,从1开始到更大,只要乘积超过1e9直接停就可以了,最后要注意,如果一个数是0,乘积就肯定是0,所以0是很容易达成的,直接在一开始把0加入到可以得到的集合中,之后询问时每次查找集合中有没有这个数就可以了
#include <bits/stdc++.h>
using namespace std;
#define int long long
using i64 = long long;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
const int N = 1000010;
const int maxn = 1e6;
const int mod = 1e9 + 7;
void solve()
{
int n, q;
cin >> n >> q;
vector<int> a(n);
for (int i = 0; i < n; i ++ ) cin >> a[i];
sort(a.begin(), a.end());
set<int> st;
st.insert(0);
auto check = [&](int x)
{
int res = 1;
for (int i = 0; i < n; i ++ )
{
res *= a[i] + x;
if (res > 1e9) return false;
}
st.insert(res);
return true;
};
for (int i = 0; i < n; i ++ )
{
if (i != n - 1 && a[i] == a[i - 1]) continue;
for (int j = -a[i] - 1; check(j); j -- ) ;
for (int j = -a[i] + 1; check(j); j ++ ) ;
}
while (q -- )
{
int m;
cin >> m;
cout << (st.count(m) ? "Yes" : "No") << '\n';
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
// cin >> t;
while (t -- )
{
solve();
}
}
牛客 寒假集训1E 本题又主要考察了贪心
题目链接
数据范围很小,dfs就可以
#include <bits/stdc++.h>
using namespace std;
#define int long long
using i64 = long long;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
const int N = 1000010;
void solve()
{
int n, m;
cin >> n >> m;
vector<int> a(n + 1);
for (int i = 1; i <= n; i ++ ) cin >> a[i];
vector<PII> op;
for (int i = 0; i < m; i ++ )
{
int x, y;
cin >> x >> y;
if (x == 1 || y == 1) a[1] += 3;
else op.push_back(make_pair(x, y));
}
int ans = n;
m = op.size();
function<void(int)> dfs = [&](int u)
{
if (u == m)
{
int cnt = 0;
for (int i = 2; i <= n; i ++ )
{
if (a[i] > a[1]) cnt ++ ;
}
ans = min(cnt + 1, ans);
return;
}
int id1 = op[u].first, id2 = op[u].second;
a[id1] ++ , a[id2] ++ ;
dfs(u + 1);
a[id1] += 2, a[id2] -- ;
dfs(u + 1);
a[id1] -= 3, a[id2] += 3;
dfs(u + 1);
a[id2] -= 3;
};
dfs(0);
cout << ans << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t -- )
{
solve();
}
}
牛客 寒假集训1G why买外卖
题目链接
优惠券按照a排序,遍历一遍即可,利用前缀和
#include <bits/stdc++.h>
using namespace std;
#define int long long
using i64 = long long;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
const int N = 1000010;
bool cmp(PII a, PII b)
{
if (a.first != b.first) return a.first < b.first;
else return a.second > b.second;
}
void solve()
{
int n, m;
cin >> n >> m;
vector<PII> info(n);
for (int i = 0; i < n; i ++ ) cin >> info[i].first >> info[i].second;
sort(info.begin(), info.end(), cmp);
int pre = 0;
int i = 0, ans = m;
for (i = 0; i < n; i ++ )
{
pre += info[i].second;
if (info[i].first - pre > m) continue;
else
{
int used = info[i].first - pre;
ans = max(ans, info[i].first + m - used);
}
}
cout << ans << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t -- )
{
solve();
}
}
牛客 寒假集训1H 01背包,但是bit
题目链接
按照题解思路写的,枚举m的二进制中的每一位1,让最后的总重量在该位为0,在这一位之后的可以随便取,在这一位之前的必须是m的子集(意思是m那一位不为1的,总重量的那一位也不能为1),取最大值即可
#include <bits/stdc++.h>
using namespace std;
#define int long long
using i64 = long long;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
const int N = 1000010;
const int maxn = 1e5 + 1;
const int mod = 1e9 + 7;
void solve()
{
int n, m;
cin >> n >> m;
vector<int> v(n), w(n);
for (int i = 0; i < n; i ++ ) cin >> v[i] >> w[i];
int ans = 0;
for (int j = 0; j < n; j ++ )
{
bool flag = true;
for (int k = 0; k <= 30; k ++ )
{
if ((((w[j] >> k) & 1) == 1) && (((m >> k) & 1) == 0))
{
flag = false;
break;
}
}
if (flag) ans += v[j];
}
for (int i = 0; i <= 30; i ++ )
{
if ((m & (1 << i)) == 0) continue;
int tmp = 0;
for (int j = 0; j < n; j ++ )
{
bool flag = true;
if (((w[j] >> i) & 1) == 1) continue;
for (int k = i + 1; k <= 30; k ++ )
{
if ((((w[j] >> k) & 1) == 1) && (((m >> k) & 1) == 0))
{
flag = false;
break;
}
}
if (flag) tmp += v[j];
}
ans = max(ans, tmp);
}
cout << ans << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t -- )
{
solve();
}
}