# Educational Codeforces Round 76 (Rated for Div. 2)

## A - Two Rival Students

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

int main() {
#ifdef KisekiPurin
freopen("KisekiPurin.in", "r", stdin);
#endif // KisekiPurin
int t;
scanf("%d", &t);
while(t--) {
int n, x, a, b;
scanf("%d%d%d%d", &n, &x, &a, &b);
printf("%d\n", min(n - 1, abs(a - b) + x));
}
return 0;
}

## B - Magic Stick

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

int main() {
#ifdef KisekiPurin
freopen("KisekiPurin.in", "r", stdin);
#endif // KisekiPurin
int t;
scanf("%d", &t);
while(t--) {
ll x, y;
scanf("%lld%lld", &x, &y);
bool suc = 0;
if(x == 1)
suc = (y <= 1);
else if(x <= 3)
suc = (y <= 3);
else
suc = 1;
puts(suc ? "YES" : "NO");
}
return 0;
}

## C - Dominated Subarray

1
7
2 2 4 4 2 2 4

x,y1,y2,y3,...,yk,x

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

int n, a[200005];
int pre[200005];

int main() {
#ifdef KisekiPurin
freopen("KisekiPurin.in", "r", stdin);
#endif // KisekiPurin
int t;
scanf("%d", &t);
while(t--) {
scanf("%d", &n);
memset(pre, -1, sizeof(pre[0]) * (n + 1));
for(int i = 1; i <= n; ++i)
scanf("%d", &a[i]);

int minlen = 1e9;
for(int i = 1; i <= n; ++i) {
if(pre[a[i]] != -1)
minlen = min(minlen, i - pre[a[i]] + 1);
pre[a[i]] = i;
}
if(minlen == 1e9)
minlen = -1;

printf("%d\n", solve());
}
return 0;
}

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

int n, a[200005];
int occ[200005];
int maxi[200005];

bool check(int len) {
memset(occ, 0, sizeof(occ[0]) * (n + 1));
memset(maxi, 0, sizeof(maxi[0]) * (n + 1));
int maxtop = 0;
for(int i = 1; i <= len; ++i) {
--maxi[occ[a[i]]];
++occ[a[i]];
++maxi[occ[a[i]]];
maxtop = max(maxtop, occ[a[i]]);
}
if(maxi[maxtop] == 1)
return 1;
else {
for(int i = len + 1; i <= n; ++i) {
--maxi[occ[a[i]]];
++occ[a[i]];
++maxi[occ[a[i]]];

--maxi[occ[a[i - len]]];
--occ[a[i - len]];
++maxi[occ[a[i - len]]];
while(maxi[maxtop] == 0)
--maxtop;
maxtop = max(maxtop, occ[a[i]]);
if(maxi[maxtop] == 1)
return 1;
}
}
return 0;
}

int solve() {
int l = 2, r = n;
//printf("l=%d r=%d\n", l, r);
while(1) {
int m = l + r >> 1;
printf("m=%d\n", m);
if(l == m) {
if(check(l))
return l;
else if(check(r))
return r;
else
return -1;
}
if(check(m))
r = m;
else
l = m + 1;
}
}

int main() {
#ifdef KisekiPurin
freopen("KisekiPurin.in", "r", stdin);
#endif // KisekiPurin
int t;
scanf("%d", &t);
while(t--) {
scanf("%d", &n);
for(int i = 1; i <= n; ++i)
scanf("%d", &a[i]);
if(n == 1) {
puts("-1");
continue;
}
printf("%d\n", solve());
}
return 0;
}

## D - Yet Another Monster Killing Problem

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

struct Hero {
int s, p;
bool operator<(const Hero &h)const {
return s != h.s ? s < h.s : p < h.p;
}
} h[200005], H[200005];
int n, hn, a[200005];
int st[200005], stop;

int id[200005];
//耐力超过i的攻击力最高的英雄的编号为id[i];
int cur;

class ST_Table {
private:
static const int MAXLOGN = 19;
static const int MAXN = 200005;
int n, logn[MAXN + 5];
int f[MAXN + 5][MAXLOGN + 1];

public:
void init1() {
logn[1] = 0;
for(int i = 2; i <= MAXN; i++)
logn[i] = logn[i >> 1] + 1;
}

void init2(int _n) {
n = _n;
for(int i = 1; i <= n; i++)
f[i][0] = a[i];
for(int j = 1, maxlogn = logn[n]; j <= maxlogn; j++) {
for(int i = 1; i + (1 << j) - 1 <= n; i++)
f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
}
}

int query(int l, int r) {
//        l = max(1, l), r = min(n, r);
//        if(l > r)
//            exit(-1);
int s = logn[r - l + 1];
return max(f[l][s], f[r - (1 << s) + 1][s]);
}
} ST;

bool check(int len) {
int p = id[len];
if(p == -1)
return 0;
else
return H[p].p >= ST.query(cur + 1, min(n, cur + len));
}

int solve() {
int l = 1, r = H[hn].s;
while(1) {
int m = l + r >> 1;
if(l == m) {
if(check(r))
return r;
else if(check(l))
return l;
else
return -1;
}
if(check(m))
l = m;
else
r = m - 1;
}
}

int main() {
#ifdef KisekiPurin
freopen("KisekiPurin.in", "r", stdin);
#endif // KisekiPurin
ST.init1();
int t;
scanf("%d", &t);
while(t--) {
scanf("%d", &n);
for(int i = 1; i <= n; ++i)
scanf("%d", &a[i]);

ST.init2(n);
scanf("%d", &hn);
for(int i = 1; i <= hn; ++i) {
scanf("%d%d", &h[i].p, &h[i].s);
}
sort(h + 1, h + 1 + hn);
stop = 0;
for(int i = 1; i <= hn; ++i) {
while(stop && h[i].p >= h[st[stop]].p)
--stop;
st[++stop] = i;
}

hn = stop;
for(int i = 1; i <= hn; ++i)
H[i] = h[st[i]];

for(int i = 1, curid = 1; i <= n; ++i) {
while(curid <= hn && H[curid].s < i)
++curid;
if(H[curid].s >= i)
id[i] = curid;
else
id[i] = -1;
}

cur = 0;
int ans = 0;
while(cur < n) {
int d = solve();
if(d == -1) {
ans = -1;
break;
} else {
cur += d;
++ans;
}
}
printf("%d\n", ans);
}
return 0;
}

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

int n, m, a[200005];
int p[200005];
//p[i]表示s超过i的最高攻击力

int main() {
#ifdef KisekiPurin
freopen("KisekiPurin.in", "r", stdin);
#endif // KisekiPurin
int t;
scanf("%d", &t);
while(t--) {
scanf("%d", &n);
memset(p, -1, sizeof(p[0]) * (n + 1));

for(int i = 1; i <= n; ++i)
scanf("%d", &a[i]);

scanf("%d", &m);
for(int i = 1, pi, si; i <= m; ++i) {
scanf("%d%d", &pi, &si);
p[si] = max(p[si], pi);
}

for(int i = n - 1; i >= 1; --i)
p[i] = max(p[i], p[i + 1]);

int i = 0, j = 0, rmq = -1, ans = 1;
while(j < n) {
++j;
rmq = max(rmq, a[j]);
if(p[j - i] < rmq) {
if(rmq > p[1]) {
ans = -1;
break;
} else {
i = j - 1;
++ans;
rmq = a[j];
}
}
}
printf("%d\n", ans);
}
return 0;
}

## E - The Contest

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

int a[200005], b[200005], c[200005];
int dp[200005];

int main() {
#ifdef KisekiPurin
freopen("KisekiPurin.in", "r", stdin);
#endif // KisekiPurin
int A, B, C;
scanf("%d%d%d", &A, &B, &C);
for(int i = 1; i <= A; ++i)
scanf("%d", &a[i]);
sort(a + 1, a + 1 + A, greater<int>());
for(int i = 1; i <= B; ++i)
scanf("%d", &b[i]);
for(int i = 1; i <= C; ++i)
scanf("%d", &c[i]);
sort(c + 1, c + 1 + C);

int ans = 0;
if(A) {
int cnt1 = 0, cnt2 = 0;
for(int i = 1; i <= A; ++i) {
cnt2 += 1;
cnt1 += (i > 1) ? (a[i - 1] - a[i] - 1) : 0;
dp[i] = dp[i - 1] + min(cnt1, cnt2);
}
ans += dp[A];
}

if(C) {
int cnt1 = 0, cnt2 = 0;
for(int i = 1; i <= C; ++i) {
cnt2 += 1;
cnt1 += (i > 1) ? (c[i] - c[i - 1] - 1) : 0;
dp[i] = dp[i - 1] + min(cnt1, cnt2);
}
ans += dp[C];
}
printf("%d\n", ans);

return 0;
}

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

int id[200005], dp[200005][4];

int main() {
#ifdef KisekiPurin
freopen("KisekiPurin.in", "r", stdin);
#endif // KisekiPurin
int A, B, C;
scanf("%d%d%d", &A, &B, &C);
for(int i = 1, ai; i <= A; ++i) {
scanf("%d", &ai);
id[ai] = 1;
}
for(int i = 1, bi; i <= B; ++i) {
scanf("%d", &bi);
id[bi] = 2;
}
for(int i = 1, ci; i <= C; ++i) {
scanf("%d", &ci);
id[ci] = 3;
}

int n = A + B + C;
for(int i = 1; i <= n; ++i) {
if(id[i] == 1) {
dp[i][1] = dp[i - 1][1];
dp[i][2] = min(dp[i - 1][1], dp[i - 1][2]) + 1;
dp[i][3] = min(dp[i - 1][1], min(dp[i - 1][2], dp[i - 1][3])) + 1;
} else if(id[i] == 2) {
dp[i][1] = dp[i - 1][1] + 1;
dp[i][2] = min(dp[i - 1][1], dp[i - 1][2]);
dp[i][3] = min(dp[i - 1][1], min(dp[i - 1][2], dp[i - 1][3])) + 1;
} else {
dp[i][1] = dp[i - 1][1] + 1;
dp[i][2] = min(dp[i - 1][1], dp[i - 1][2]) + 1;
dp[i][3] = min(dp[i - 1][1], min(dp[i - 1][2], dp[i - 1][3]));
}
}

printf("%d\n", min(dp[n][1], min(dp[n][2], dp[n][3])));
return 0;
}

## F - Make Them Similar

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

int a[105];
map<vector<int>, int> m;

int main() {
#ifdef KisekiPurin
freopen("KisekiPurin.in", "r", stdin);
#endif // KisekiPurin
int n;
scanf("%d", &n);
for(int i = 1; i <= n; ++i)
scanf("%d", &a[i]);

vector<int> vec(n);

const int BIT = 15;
//处理高15位，并存表
for(int x = 0; x < (1 << BIT); ++x) {
for(int i = 1; i <= n; ++i)
vec[i - 1] = __builtin_popcount((a[i] >> BIT)^x);
for(int i = n; i >= 1; --i)
vec[i - 1] -= vec[0];
m[vec] = x;
}

//处理低15位，并查表
const int BITMASK = (1 << BIT) - 1;
for(int x = 0; x < (1 << BIT); ++x) {
for(int i = 1; i <= n; ++i)
vec[i - 1] = __builtin_popcount((a[i] & BITMASK)^x);
for(int i = n; i >= 1; --i)
vec[i - 1] = vec[0] - vec[i - 1];
auto it = m.find(vec);
if(it != m.end()) {
printf("%d", ((it->second) << BIT) | x);
return 0;
}
}

puts("-1");
return 0;
}

1、不要把按位与写成逻辑与！
2、提示我可以使用一个Trie，每一层是固定的31个节点[-15,15]。要把这个Trie改成每层使用map的感觉也很简单，就修改一个TrieNode就可以了。

## G - Divisor Set

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

int a[200005], b[200005], btop;

const int MAXN = 1e6, MAXLOGN = 20, mod = 998244353;

int add_mod(int x, int y) {
x += y;
if(x >= mod)
x -= mod;
return x;
}

int sub_mod(int x, int y) {
x -= y;
if(x < 0)
x += mod;
return x;
}

ll mul_mod(ll x, int y) {
x *= y;
if(x >= mod)
x %= mod;
return x;
}

int pow_mod(ll x, int n) {
ll res = 1;
while(n) {
if(n & 1)
res = mul_mod(res, x);
x = mul_mod(x, x);
n >>= 1;
}
return res;
}

int gl[MAXLOGN + 1];

void init() {
for(int len = 2; len <= MAXN; len <<= 1)
gl[__builtin_ctz(len)] = pow_mod(3, (mod - 1) / len);
}

void NTT(int a[], int n, int op) {
for(int i = 1, j = n >> 1; i < n - 1; ++i) {
if(i < j)
swap(a[i], a[j]);
int k = n >> 1;
while(k <= j) {
j -= k;
k >>= 1;
}
j += k;
}
for(int len = 2; len <= n; len <<= 1) {
int g = gl[__builtin_ctz(len)];
for(int i = 0; i < n; i += len) {
int w = 1;
for(int j = i; j < i + (len >> 1); ++j) {
int u = a[j], t = mul_mod(a[j + (len >> 1)], w);
a[j] = add_mod(u, t), a[j + (len >> 1)] = sub_mod(u, t);
w = mul_mod(w, g);
}
}
}
if(op == -1) {
reverse(a + 1, a + n);
int inv = pow_mod(n, mod - 2);
for(int i = 0; i < n; ++i)
a[i] = mul_mod(a[i], inv);
}
}

int A[MAXN + 5], B[MAXN + 5];

int pow2(int x) {
int res = 1;
while(res < x)
res <<= 1;
return res;
}

void convolution(int A[], int B[], int Asize, int Bsize) {
int n = pow2(Asize + Bsize - 1);
memset(A + Asize, 0, sizeof(A[0]) * (n - Asize));
memset(B + Bsize, 0, sizeof(B[0]) * (n - Bsize));
NTT(A, n, 1);
NTT(B, n, 1);
for(int i = 0; i < n; ++i)
A[i] = mul_mod(A[i], B[i]);
NTT(A, n, -1);
return;
}

vector<int> vec[200005], evec;
struct PriorityQueueNode {
int siz, id;
bool operator<(const PriorityQueueNode &pqn) const {
return siz > pqn.siz;
}
} pqn;

priority_queue<PriorityQueueNode> pq;

void solve() {
//哈夫曼分治
init();
while(pq.size() > 1) {
int Aid = pq.top().id, Asize = vec[Aid].size();
for(int i = 0; i < Asize; ++i)
A[i] = vec[Aid][i];
pq.pop();

int Bid = pq.top().id, Bsize = vec[Bid].size();
for(int i = 0; i < Bsize; ++i)
B[i] = vec[Bid][i];
pq.pop();

convolution(A, B, Asize, Bsize);
Asize = Asize + Bsize - 1;

vec[Aid].resize(Asize);
for(int i = 0; i < Asize; ++i)
vec[Aid][i] = A[i];
pq.push({Asize, Aid});
vec[Bid] = evec;
}
}

int main() {
#ifdef KisekiPurin
freopen("KisekiPurin.in", "r", stdin);
#endif // KisekiPurin
int n;
scanf("%d", &n);
for(int i = 1; i <= n; ++i)
scanf("%d", &a[i]);
sort(a + 1, a + 1 + n);

btop = 0;
for(int i = 1; i <= n; ++i) {
if(a[i] != a[i - 1])
b[++btop] = 1;
else
++b[btop];
}

sort(b + 1, b + 1 + btop);
for(int i = 1; i <= btop; ++i) {
while(vec[0].size() < b[i] + 1)
vec[0].push_back(1);
vec[i] = vec[0];
pq.push({vec[i].size(), i});
}

solve();

printf("%d\n", vec[pq.top().id][pq.top().siz >> 1]);

return 0;
}

upd1：偏序关系可以画出（化简的，也就是没有多余边的）哈斯图。哈斯图是分层的，覆盖关系连出有向边。画多几个（打表）发现哈斯图上下对称且中间是比较宽的。已知同一层的节点一定满足题意，但是为什么一定只选择同一层的呢。（题解说用OEIS，真就打表暴力啊）

## 参考资料：

[Educational Codeforces Round 76 Editorial - Codeforces]https://codeforces.com/blog/entry/71434

posted @ 2019-11-14 08:50  KisekiPurin2019  阅读(...)  评论(...编辑  收藏