Codeforces Round 1038, Div. 1 + Div. 2 (A-E)
C
一维的时候分成两组,二维的时候怎么办?
我们发现只考虑一维时sort后把前半部分和后半部分的点随机匹配结果都是相同的,也是最优的。
二维按x,y分为四个部分,刚好四个部分也是可以两个部分两个部分匹配的!(通过a+b=b+c可证a=c)
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define int long long
#define endl '\n'
const int N = 2e5 + 8;
struct Node{
int x, y, id;
}p[N];
bool cmp(const Node &x, const Node &y) {
if (x.x != y.x) return x.x < y.x;
return x.y < y.y;
}
bool cmp2(const Node &x, const Node &y) {
if (x.y != y.y) return x.y < y.y;
return x.x < y.x;
}
void solve() {
int n, m;
cin >> n;
for (int i = 1; i <= n; i++)
p[i].id = i, cin >> p[i].x >> p[i].y;
sort(p + 1, p + n + 1, cmp);
for (int i = 1; i <= n; i++) {
if (i <= n / 2) p[i].x = 0;
else p[i].x = 1;
}
sort(p + 1, p + n + 1, cmp2);
//{00} {01} {10} {11}
vector<int> a, b, c, d;
for (int i = 1; i <= n; i++) {
if (!p[i].x) {
if (i <= n / 2) a.push_back(p[i].id);
else b.push_back(p[i].id);
}
else {
if (i > n / 2) c.push_back(p[i].id);
else d.push_back(p[i].id);
}
}
// cout << a.size() << ' ' << c.size() << endl;
// return;
// cout << "XXX" << endl;
for (int i = 0; i < a.size(); i++) {
cout << a[i] << ' ' << c[i] << endl;
}
for (int i = 0; i < b.size(); i++) {
cout << b[i] << ' ' << d[i] << endl;
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;
cin>>T;
while(T--){
solve();
}
}
D
一眼bfs拆点dp。但是需要满足的最优状态有t和wait t两维复杂度太高做不到。
猜测t最高为2*n,(已有大佬证明了t最大为2n-3),那么只需要维护wait t最优即可不断转移,n方可做
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define int long long
#define endl '\n'
const int N = 5e3 + 9;
struct Node{
int x, y, id;
}p[N];
bool cmp(const Node &x, const Node &y) {
if (x.x != y.x) return x.x < y.x;
return x.y < y.y;
}
vector<int> E[N];
void solve() {
int n, m;
cin >> n >> m;
vector<vector<int>> E(n + 1);
for (int i = 1; i <= m; i++) {
int u, v;
cin >> u >> v;
E[u].push_back(v);
E[v].push_back(u);
}
vector<int> f(n + 1, 0x3f3f);
f[1] = 0;
for (int t = 0; t < 2 * n; t++) {
// cout << t << "XXX" << endl;
if (f[n] != 0x3f3f) {
cout << t << ' ' << f[n] << endl;
return;
}
vector<int> tf(n + 1, 0x3f3f);
for (int i = 1; i <= n; i++) {
int c = E[i].size();
int v = E[i][t % c];
tf[i] = min(tf[i], f[i] + 1);
tf[v] = min(tf[v], f[i]);
}
swap(f, tf);
}
}
signed main()
{
// ios::sync_with_stdio(false);
// cin.tie(nullptr);
int T;
cin>>T;
while(T--){
solve();
}
}
E
看tourist代码学习而得。
如果新的\({c_i}\)小于0那么就重置,否则就更新
#include<bits/stdc++.h>
using namespace std;
#define ll long long
// #define int long long
#define endl '\n'
const int N = 2e5 + 8;
const int mod = 998244353;
int add(int x) {return x > mod ? x - mod : x;}
int mul(int x, int y) {return (1ll * x * y % mod);}
int a[2][N];
void solve() {
int n, k;
cin >> n >> k;
for (int i = 0; i < 2; i++) {
for (int j = 0; j < n; j++) {
cin >> a[i][j];
}
}
vector<int> f(k + 1, 0);
f[k] = 1;
for (int i = 1; i < n; i++) {
vector<int> w(2* k+1, 0);
for (int x = 1; x <= k; x++) {
if (x != -1 && a[0][i] != -1 && x != a[0][i]) continue;
for (int y = 1; y <= k; y++) {
if (y != -1 && a[1][i - 1] != -1 && a[1][i - 1] != y) continue;
w[x - y + k]++;
}
}
vector<int> tf(k + 1, 0);
for (int p = 0; p <= k; p++) {
// cout << p << endl;
if (f[p] == 0) continue;
int tp = p;
for (int d = -k + 1; d <= k - 1; d++) {
if (p == k) {
if (d >= 0)
tp = k;
else
tp = -d;
}
else {
if (p - d < 0) continue;
if (d < 0) tp = -d;
else tp = p - d;
}
assert(tp >= 0 && tp <= k);
tf[tp] = add(tf[tp] + mul(f[p], w[d + k]));
}
}
swap(f, tf);
}
int ans = 0;
for (int i = 0; i <= k; i++) ans = add(ans + f[i]);
if (a[0][0] == -1) ans = mul(ans, k);
if (a[1][n - 1] == -1) ans = mul(ans, k);
cout << ans << endl;
}
signed main()
{
// ios::sync_with_stdio(false);
// cin.tie(nullptr);
int T;
cin>>T;
while(T--){
solve();
}
}

浙公网安备 33010602011771号