2026.10.10 联考总结

联考总结

估:100 + 10 + 100 + 56

实:100 + 10 + 100 + 56 rk5

饭堂了没有做出来 t2 的唐题。

T1

给定 DAG 问有没有长度为 \(n\) 的链。

直接拓扑排序即可。

T2

原:P6940 [ICPC 2017 WF] Visual Python++

没有做出来,怎么会使呢。

考虑先从右往左扫描线,每次将右下角加入 set,左上角配对直接找高度大于等于他且最小的显然不劣,lower_bound 即可,找不到无解。然后再来判别的无解条件,不难发现无解时一定存在边框相交,考虑扫描线,线段树维护一个点上有多少个边框,存在值 \(\ge 2\) 无解。做完了,注意要离散化。

code
#include <bits/stdc++.h>
using namespace std;
#define int int
#define ll long long
#define usd unsigned
#define el putchar('\n')
#define lowbit(x) (x & (-x))
#define AC return 
#define AK return 0
#define YS cout << "YES"
#define NO cout << "NO"
#define Ys cout << "Yes"
#define No cout << "No"
#define ys cout << "yes"
#define no cout << "no"
#define ls(i) ch[i][0]
#define rs(i) ch[i][1]
#define debug(num) cerr << #num << ' ' << num << '\n'
#define void inline void
#define il inline
#define Mod(x) (((x) % mod + mod) % mod)
#define pii pair <int, int>
#define pll pair <ll, ll>
il char gc() { char c; while((c = getchar()) <= ' ') ; return c; }
il int rd() {
	char c; int x, f = 1;
	while(!isdigit(c = getchar())) if(c == '-') f *= -1;
	x = c ^ 48;
	while(isdigit(c = getchar())) x = (x << 3) + (x << 1) + (c ^ 48);
	return x * f;
}
void ACehomoxue();
signed main() {
	srand(time(0));
	// freopen("rectangle_sample5.in", "r", stdin);
	// freopen(".out", "w", stdout);
	int t = 1;
	// t = rd();
	while(t--) ACehomoxue();
	AK;
}
const int mod = 998244353, maxn = 2 * 1e5 + 18;

int n, sx, sy, ans[maxn];
struct node {
    int x, y;
} s[maxn], t[maxn];
set <pii> p;
vector <int> tx, ty, upd[maxn], ask[maxn];
struct mdf {
    int l, r, x;
} ;
vector <mdf> dif[maxn];

class xds {
    struct tree {
        int l, r, t, v;
    } t[maxn << 2];
    void push_up(int i) { t[i].v = max(t[i << 1].v, t[i << 1 | 1].v); }
    void push_down(int i) {
        t[i << 1].t += t[i].t;
        t[i << 1].v += t[i].t;
        t[i << 1 | 1].t += t[i].t;
        t[i << 1 | 1].v += t[i].t;
        t[i].t = 0;
    }
public:
    void build(int i, int l, int r) {
        t[i].l = l, t[i].r = r, t[i].v = t[i].t = 0;
        if(l == r) AC;
        int mid = l + r >> 1;
        build(i << 1, l, mid);
        build(i << 1 | 1, mid + 1, r);
    }
    void updata(int i, int l, int r, int x) {
        if(t[i].l >= l && t[i].r <= r) {
            t[i].t += x, t[i].v += x;
            AC;
        }
        push_down(i);
        int mid = t[i].l + t[i].r >> 1;
        if(l <= mid) updata(i << 1, l, r, x);
        if(r > mid) updata(i << 1 | 1, l, r, x);
        push_up(i);
    }
    il bool chk() { return t[1].v <= 1; }
} ds;

void ACehomoxue() {
	n = rd();
    for(int i = 1; i <= n; i++) s[i] = {rd(), rd()};
    for(int i = 1; i <= n; i++) t[i] = {rd(), rd()};
    tx.push_back(0), ty.push_back(0);
    for(int i = 1; i <= n; i++) tx.push_back(s[i].x), tx.push_back(t[i].x), ty.push_back(s[i].y), ty.push_back(t[i].y);
    sort(tx.begin(), tx.end()), sort(ty.begin(), ty.end());
    tx.erase(unique(tx.begin(), tx.end()), tx.end());
    ty.erase(unique(ty.begin(), ty.end()), ty.end());
    for(int i = 1; i <= n; i++) {
        s[i].x = lower_bound(tx.begin(), tx.end(), s[i].x) - tx.begin();
        s[i].y = lower_bound(ty.begin(), ty.end(), s[i].y) - ty.begin();
        t[i].x = lower_bound(tx.begin(), tx.end(), t[i].x) - tx.begin();
        t[i].y = lower_bound(ty.begin(), ty.end(), t[i].y) - ty.begin();
        upd[t[i].x].push_back(i);
        ask[s[i].x].push_back(i);
    }
    sx = tx.size() - 1, sy = ty.size() - 1;
    for(int x = sx; x; x--) {
        for(int i : upd[x]) {
            int y = t[i].y;
            p.insert({y, i});
        }
        for(int i : ask[x]) {
            int y = s[i].y;
            auto it = p.lower_bound(make_pair(y, 0));
            if(it == p.end()) { cout << "syntax error"; el; AC; }
            ans[i] = it -> second;
            p.erase(it);
        }
    }   
    for(int i = 1; i <= n; i++) {
        int a = s[i].x, b = s[i].y, c = t[ans[i]].x, d = t[ans[i]].y;
        if(a == c) {
            dif[a].push_back({b, d, 1});
            dif[c + 1].push_back({b, d, -1});
            continue;
        } 
        dif[a].push_back({b, d, 1});
        dif[a + 1].push_back({b + 1, d - 1, -1});
        dif[c].push_back({b + 1, d - 1, 1});
        dif[c + 1].push_back({b, d, -1});
    }
    ds.build(1, 1, sy);
    for(int i = 1; i <= sx; i++) {
        for(auto [l, r, x] : dif[i]) if(l <= r) ds.updata(1, l, r, x);
        if(!ds.chk()) { cout << "syntax error"; el; AC; }
    }
    for(int i = 1; i <= n; i++) cout << ans[i], el;
}

T3

原:P13552 鱼类考古学

注意到先与后加不劣,应为一次与为 \(x + y - x | y\),相当于 \(x | y\) 为代价,且不难发现约加代价越大。考虑将数字分成 \(k\) 组与起来然后加起来。考虑按位贪心,对于枚举到第 \(d\) 位有 \(c0\) 个为 \(0\) 有 \(c1\) 个为 \(1\),我们尽量让为 \(1\) 的全都单独一组,所以 \(k > c1\) 时直接让为 \(1\) 的单独一组对为 \(0\) 的算下一位即可。否则为 \(0\) 的一定要全部在一组里面不劣,将其全部与起来当成一个数,且这一位显然对答案有贡献 \((k - 1) \times 2 ^ d\),递归下一位即可。做完了,设 \(V\) 表示值域,有时间复杂度 \(O(n \log V)\)。

code
#include <bits/stdc++.h>
using namespace std;
#define int ll
#define ll long long
#define usd unsigned
#define el putchar('\n')
#define lowbit(x) (x & (-x))
#define AC return 
#define AK return 0
#define YS cout << "YES"
#define NO cout << "NO"
#define Ys cout << "Yes"
#define No cout << "No"
#define ys cout << "yes"
#define no cout << "no"
#define ls(i) ch[i][0]
#define rs(i) ch[i][1]
#define debug(num) cerr << #num << ' ' << num << '\n'
#define void inline void
#define il inline
#define Mod(x) (((x) % mod + mod) % mod)
#define pii pair <int, int>
#define pll pair <ll, ll>
il char gc() { char c; while((c = getchar()) <= ' ') ; return c; }
il int rd() {
	char c; int x, f = 1;
	while(!isdigit(c = getchar())) if(c == '-') f *= -1;
	x = c ^ 48;
	while(isdigit(c = getchar())) x = (x << 3) + (x << 1) + (c ^ 48);
	return x * f;
}
void ACehomoxue();
signed main() {
	srand(time(0));
	int t = 1;
	t = rd();
	while(t--) ACehomoxue();
	AK;
}
const int mod = 998244353, maxn = 1e6 + 18;

int n, k, a[maxn], ans;

const int maxs = maxn * 30;
vector <int> p, p0, p1;

void ACehomoxue() {
    p.clear(), p0.clear(), p1.clear();
    n = rd(), k = rd(), ans = 0;
    for(int i = 1; i <= n; i++) {
        a[i] = rd();
        p.push_back(a[i]);
    }
    for(int d = 30; d + 1; d--) {
        if(p.empty()) break;
        p0.clear(), p1.clear();
        if(k == (ll) p.size()) { for(int i : p) ans += i; break; }
        if(k == 1) {
            int v = p[0];
            for(int i : p) v &= i;
            ans += v;
            break;
        }
        for(int i : p) {
            if((i >> d) & 1) p1.push_back(i);
            else p0.push_back(i);
        }
        if(p1.empty()) { p = p0; continue; }
        if(p0.empty()) {
            ans += k * (1 << d);
            for(int &i : p1) i ^= 1 << d;
            p = p1;
            continue;
        }
        if(k > (ll) p1.size()) {
            for(int i : p1) ans += i;
            k -= p1.size();
            p = p0;
        } else {
            int v = p0[0];
            for(int i : p0) v &= i;
            ans += (k - 1) * (1 << d);
            for(int &i : p1) i ^= 1 << d;
            p = p1;
            p.push_back(v);
        }
    }
    cout << ans;
    el;
}

T4

原:P14211 [ROI 2016 Day2] 快递服务

给你一棵树和一堆路径,求两条路径最大相交长度和两者编号。

set 简单应用。

贡献分两种。将一条路径 \((u, v)\) 划为两条,分别是 \((u, w)\) 和 \((v, w)\) 其中 \(w\) 表示 \(\operatorname{lca}(u, v)\)。按照路径 \(w\) 是否相同分类,\(w\) 不同只需算每个 \((w, v)\) 和 \((w, u)\) 公共长度即可。

对于每个节点 \(x\),我们开个 set 维护 \((u, w)\) 和 \((v, w)\) 且 \(u\) 和 \(v\) 都在子树内 \(w\) 为 \(x\) 祖先。启发式合并,当两个集合于 \(x\) 合并,显然里面所有 \(u\) 啊 \(v\) 啊的 lca 都应在 \(x\),不难发现答案为 \(dep_{\max w} - dep_{x}\)。由于答案尽量大所以我们其实不需 set,只需开两个数组存储 \(w\) 深度最小的即可,可以做到 \(O(n)\)。

对于 \(w\) 在同一节点,类似的开 set 启发式合并,对于 \((u, v)\) 要合并进入集合 \(t\) 在点 \(x\),不难发现其贡献为 \(dep_x + dep_{\max_{v ^ \prime \in t} \operatorname{lca}(v, v ^ \prime)} - 2 dep_w\),即要找到集合中 \(v ^ \prime\) 和 \(v\) 的 lca 深度最大的,有结论其应和 \(v\) 的 dfs 序尽量接近,那么这部分的 set 就按 dfs 序排序即可,查询时简单 lower_bound,时间复杂度 \(O(n \log ^ 2 n)\)。

做完了。

code
#include <bits/stdc++.h>
using namespace std;
#define int int
#define ll long long
#define usd unsigned
#define el putchar('\n')
#define lowbit(x) (x & (-x))
#define AC return
#define AK return 0
#define YS cout << "YES"
#define NO cout << "NO"
#define Ys cout << "Yes"
#define No cout << "No"
#define ys cout << "yes"
#define no cout << "no"
#define ls(i) ch[i][0]
#define rs(i) ch[i][1]
#define debug(num) cerr << #num << ' ' << num << '\n'
#define void inline void
#define il inline
#define Mod(x) (((x) % mod + mod) % mod)
#define pii pair <int, int>
#define pll pair <ll, ll>
il char gc() { char c; while((c = getchar()) <= ' ') ; return c; }
il int rd() {
    char c; int x, f = 1;
    while(!isdigit(c = getchar())) if(c == '-') f *= -1;
    x = c ^ 48;
    while(isdigit(c = getchar())) x = (x << 3) + (x << 1) + (c ^ 48);
    return x * f;
}
void ACehomoxue();
signed main() {
    srand(time(0));
    // freopen(".in", "r", stdin);
    // freopen(".out", "w", stdout);
    int t = 1;
    // t = rd();
    while(t--) ACehomoxue();
    AK;
}
const int mod = 998244353, maxn = 2 * 1e5 + 18, maxk = 19;
int n, m, nxt[maxn][maxk], dep[maxn], fa[maxn], lg[maxn];
int ans, x1 = 1, x2 = 2, in[maxn], dfn, rfl[maxn], stk[maxn];
vector <int> vec[maxn], pt[maxn];
pii e[maxn], mn[maxn];
set <pii, greater<> > s[maxn];
il int mindep(int u, int v) {
    return dep[u] < dep[v] ? u : v;
}
void g1() {
    int top = 0;
    stk[++top] = 1, dep[1] = 1;
    while(top) {
        int x = stk[top--];
        in[x] = ++dfn, rfl[dfn] = x;
        for(int i = (int)vec[x].size() - 1; i + 1; i--) {
            int to = vec[x][i];
            dep[to] = dep[x] + 1;
            stk[++top] = to;
        }
    }
    for(int i = 2; i <= n; i++) lg[i] = lg[i >> 1] + 1;
    for(int i = 1; i <= n; i++) nxt[i][0] = fa[rfl[i]];
    for(int j = 1; j < maxk; j++)
        for(int i = 1; i + (1 << j) - 1 <= n; i++)
            nxt[i][j] = mindep(nxt[i][j - 1], nxt[i + (1 << (j - 1))][j - 1]);
}
il int lca(int u, int v) {
    if(u == v) return u;
    int l = in[u], r = in[v];
    if(l > r) swap(l, r);
    l++;
    int k = lg[r - l + 1];
    return mindep(nxt[l][k], nxt[r - (1 << k) + 1][k]);
}
void upd(int x, int d, int i) {
    if(d >= dep[x]) AC;
    if(mn[x].second) {
        int val = dep[x] - max(d, mn[x].first);
        if(val > ans) ans = val, x1 = i, x2 = mn[x].second;
    }
    if(!mn[x].second || d < mn[x].first) mn[x] = {d, i};
}
void g2() {
    for(int i = n; i > 1; i--) {
        int x = rfl[i];
        if(mn[x].second) upd(fa[x], mn[x].first, mn[x].second);
    }
}
il bool cmp(const int &i, const int &j) {
    return in[i] < in[j];
}
class vt {
    vector <int> vec[maxn], p;
    bool vis[maxn];
    int depp;
    void dfs(int x) {
        if(s[x].size() > 1) {
            auto it = s[x].begin(), pre = it++;
            for(; it != s[x].end(); pre = it++) {
                int val = dep[x] - 2 * depp
                        + dep[lca(rfl[pre -> first], rfl[it -> first])];
                if(val > ans) ans = val, x1 = pre -> second, x2 = it -> second;
            }
        }
        for(int to : vec[x]) {
            if(s[to].size() > s[x].size()) swap(s[x], s[to]);
            for(pii pr : s[to]) {
                int nx = pr.first, i = pr.second;
                auto it = s[x].lower_bound({nx, 0});
                if(it != s[x].end()) {
                    int val = dep[x] - 2 * depp
                            + dep[lca(rfl[nx], rfl[it -> first])];
                    if(val > ans) ans = val, x1 = i, x2 = it -> second;
                }
                if(it != s[x].begin()) {
                    it--;
                    int val = dep[x] - 2 * depp
                            + dep[lca(rfl[nx], rfl[it -> first])];
                    if(val > ans) ans = val, x1 = i, x2 = it -> second;
                }
            }
            s[x].merge(s[to]);
        }
    }
public:
    void sol(int w) {
        for(int i : p) vis[i] = false, vec[i].clear(), s[i].clear();
        p.clear(), p.push_back(w);
        vis[w] = true;
        for(int i : pt[w]) {
            auto [u, v] = e[i];
            if(!vis[u]) vis[u] = true, p.push_back(u);
            if(!vis[v]) vis[v] = true, p.push_back(v);
        }
        sort(p.begin(), p.end(), cmp);
        for(int i = 1, sz = p.size(); i < sz; i++) {
            int x = lca(p[i - 1], p[i]);
            if(!vis[x]) vis[x] = true, p.push_back(x);
        }
        sort(p.begin(), p.end(), cmp);
        for(int i = 1, sz = p.size(); i < sz; i++)
            vec[lca(p[i - 1], p[i])].push_back(p[i]);
        depp = dep[w];
        for(int i : pt[w]) {
            auto [u, v] = e[i];
            s[u].insert({in[v], i});
            s[v].insert({in[u], i});
        }
        for(int i = (int)p.size() - 1; i; i--) dfs(p[i]);
    }
} ss;
void ACehomoxue() {
    n = rd(), m = rd();
    for(int i = 2; i <= n; i++) {
        fa[i] = rd();
        vec[fa[i]].push_back(i);
    }
    g1();
    for(int i = 1; i <= m; i++) {
        int u = rd(), v = rd(), w = lca(u, v);
        e[i] = {u, v};
        upd(u, dep[w], i), upd(v, dep[w], i);
        pt[w].push_back(i);
    }
    g2();
    for(int i = 1; i <= n; i++)
        if(pt[i].size() > 1) ss.sol(i);
    cout << ans;
    el;
    cout << x1 << ' ' << x2;
    el;
}
posted @ 2026-10-11 10:59  ACehomoxue  阅读(12)  评论(0)    收藏  举报