CF 1935C Messenger in MAC
第一想法是转换成图论,每往后选一个点相当于走一条边,边的代价就是这个新点对于总体的代价贡献,然后跑最短路这样
但是是不行的!!!因为答案要求的是点的数量尽可能多,代价只需要满足条件就可以了,并不需要最小化代价,类似于这种不需要最小化代价的问题,都不可以转化成最短路来做!
理解能力有限(但我坚持认为是题目描述太抽象了!!!),没能考虑到应该最小化后半部分绝对值的大小,只要b是从大到小排序的,绝对值的部分就不需要付出多余的代价,因此按照b排序,每次枚举选的第一个点和最后一个点,看中间可以选哪些数(利用优先队列,优先选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<PII, int> PIII;
const int N = 200010;
const int mod = 998244353;
const int maxn = 1e6 + 10;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;
void solve()
{
int n, l;
cin >> n >> l;
vector<PII> a(n);
for (int i = 0; i < n; i ++ ) cin >> a[i].second >> a[i].first;
sort(a.begin(), a.end());
int ans = 0;
for (int i = 0; i < n; i ++ )
{
priority_queue<int> q;
int tmp = 0, cnt = 0;
for (int j = i; j < n; j ++ )
{
tmp += a[j].second;
cnt ++ ;
q.push(a[j].second);
while (tmp + a[j].first - a[i].first > l && q.size())
{
tmp -= q.top();
cnt -- ;
q.pop();
}
if (tmp + a[j].first - a[i].first > l) break;
ans = max(ans, 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();
}
}
CF 1935D Exam in MAC
很普的容斥,但是本人又把题看错了,xy是0-c内所有数都可以选,不是只能选集合里的数
总共能选 (c + 1) * (c + 2) / 2
组,枚举每个数分别作为x+y和y-x,每次减去 x+y 在集合里的组合 k / 2 + 1
,减去 y-x 在集合里的组合 c - x + 1
,加上 x+y 和 y-x 都在集合里的组合,这个怎么计算呢,假设 x + y = a, y - x = b
,a 和 b 都在集合中,那么 x = (a - b) / 2
y = (a + b) / 2
,我们发现只要 ab 的奇偶性相同就有解,循环中每次把当前的数当做 a ,记录前方(包括自己,因为xy可以相等)有多少和自己奇偶性相同的数,每次加上这个值即可
#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<PII, int> PIII;
const int N = 200010;
const int mod = 998244353;
const int maxn = 1e6 + 10;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;
void solve()
{
int n, c;
cin >> n >> c;
int cnt[2] = {0, 0};
int ans = (c + 1) * (c + 2) / 2;
for (int i = 0; i < n; i ++ )
{
int x; cin >> x;
ans -= x / 2 + 1;
ans -= c - x + 1;
cnt[x & 1] ++ ;
ans += cnt[x & 1];
}
cout << ans << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t -- )
{
solve();
}
}
CF 706D Vasiliy’s Multiset
第一次遇到二进制+字典树结合的题目,可以记录一下
把每个数的二进制存到字典树里,按题目进行操作就可以
#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<PII, int> PIII;
const int N = 200010 * 32;
const int mod = 998244353;
const int maxn = 1e6 + 10;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;
int nxt[N][2], idx;
int cnt[N]; // 该结点结尾的字符串是否存在
void insert(string s, int l) // 插入字符串,l是字符串长度
{
int p = 0;
for (int i = 0; i < l; i++)
{
cnt[p] ++ ;
int c = s[i] - '0';
if (!nxt[p][c]) nxt[p][c] = ++ idx; // 如果没有,就添加结点
p = nxt[p][c];
}
cnt[p] ++ ;
}
int find(string s, int l, int x) // 查找字符串,l是字符串长度
{
int p = 0;
for (int i = 0; i < l; i++)
{
int c = s[i] - '0';
if (!nxt[p][c ^ 1] || cnt[nxt[p][c ^ 1]] == 0)
{
if (c == 1) x -= (1 << (29 - i));
p = nxt[p][c];
}
else
{
if (c == 0) x += (1 << (29 - i));
p = nxt[p][c ^ 1];
}
}
return x;
}
void drop(string s, int l) // 删除字符串,l是字符串长度
{
int p = 0;
for (int i = 0; i < l; i++)
{
cnt[p] -- ;
int c = s[i] - '0';
if (!nxt[p][c]) return;
p = nxt[p][c];
}
cnt[p] -- ;
}
void solve()
{
string tt = "";
for (int i = 0; i < 30; i ++ ) tt += "0";
insert(tt, tt.size());
int q;
cin >> q;
while (q -- )
{
char ch;
int x, tmp;
cin >> ch >> x;
tmp = x;
string s = "";
while (tmp)
{
if (tmp & 1) s += "1";
else s += "0";
tmp >>= 1;
}
while (s.size() < 30) s += "0";
reverse(s.begin(), s.end());
if (ch == '+') insert(s, s.size());
else if (ch == '-') drop(s, s.size());
else if (ch == '?')
{
int tmp = find(s, s.size(), x);
cout << tmp << '\n';
}
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
// cin >> t;
while (t -- )
{
solve();
}
}
CF 580D Diane
昨晚写了没保存,懒得打字了单纯记录一下就这样吧
#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<PII, int> PIII;
const int N = 200010 * 32;
const int mod = 998244353;
const int maxn = 1e6 + 10;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;
void solve()
{
int n;
cin >> n;
if (n == 1) cout << "a\n";
else if (n == 2) cout << "ab\n";
else if (n == 3) cout << "abc\n";
else
{
string s1(n / 2, 'a'), s2(n / 2 - 1, 'a');
if (n - n / 2 - (n / 2 - 1) == 2) s1 = s1 + "bc" + s2;
else s1 = s1 + "b" + s2;
cout << s1 << '\n';
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t -- )
{
solve();
}
}