Educational Codeforces Round 10 部分题解

两道线段题,都只差一步想出正解。差的这一步还都是我见过无数遍的套路。

脑子进水生锈了属于是。

C. Foe Pairs

题意简述

给定一个长为 \(n\) 的排列,再给定 \(m\) 的无序二元组 \((x, y)\),请计算有多少个区间满足不存在两个数都出现的二元组。

或者换个描述,给定一些线段,请计算有多少个区间满足没有一条线段被完整包含。

解题报告

很显然是对每一个点往左 / 往右处理点什么东西出来,然后累计答案。然后我就死活想不出怎么处理。

实际很简单,可以用一个类似差分的思想,先处理单点再前缀扫一遍:设 \(f(i)\) 表示位置 \(i\) 往左走到最远的地方是哪,很显然对于所有右端点在 \(r\) 的线段 \([l_i, r], f(r) = \max\{l_i + 1\}.\)

然后再做一个前缀 \(\max\),就可以知道所有的 \(f(i)\)(画个图就明白了)。之后再把每个位置的 \(i - f(i) + 1\) 加起来即可。

const int MAXN = 3e5 + 10;

int n, m;
int aa[MAXN];
std::pair<int, int> foe[MAXN];

std::pair<int, int> fpos[MAXN];

bool cmp(std::pair<int, int> x, std::pair<int, int> y) {
    return x.se == y.se ? x.fi > y.fi : x.se < y.se;
}

int pos[MAXN];
int lst[MAXN];

int main() {
    std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    n = read(); m = read();
    rep (i, 1, n) pos[aa[i] = read()] = i;
    rep (i, 1, m) {
        foe[i].fi = pos[read()]; foe[i].se = pos[read()];
        if (foe[i].fi > foe[i].se) std::swap(foe[i].fi, foe[i].se);
        lst[foe[i].se] = std::max(lst[foe[i].se], foe[i].fi + 1);
    } 
    lli ans = 0;
    int x = 1;
    for (int i = 1; i <= n; ++i) {
        x = std::max(x, lst[i]);
        ans += i - x + 1;
    } 
    printf("%lld\n", ans);
    return 0;
}

D. Nested Segments

题意简述

给定 \(n\) 条线段(端点不重合),求每条线段包含了多少线段。

解题报告

首先离散化。然后把线段随便按照某个端点排序,比如右端点吧。

考虑一个线段 \([L, R]\) 包含 \([l, r]\) 的充要条件是:\(L < l < r < R\),那么按照右端点排序之后,当前这条线段前面所有的线段都是满足 \(r < R\) 的,只需要查找有多少 \(L < l\)。这个东西显然是拿树状数组边插入边查询。

const int MAXN = 2e5 + 10;

int n;
struct Seg {int l, r, id;} segs[MAXN];
bool cmp(Seg x, Seg y) { return x.r < y.r; }

int cnt; std::vector<int> lisan;

struct BIT {
    int seq[MAXN << 1];
    #define lb(x) (x & (-x))
    void mod(int x) { for (; x <= cnt; x += lb(x)) ++seq[x]; }
    int qry(int x) { 
        int r = 0; for(; x; x -= lb(x)) r += seq[x];
        return r;
    }
    int qrg(int x, int y) { return qry(y) - qry(x - 1); }
} bit;

int ans[MAXN];

int main() {
    std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    n = read();
    rep (i, 1, n) { 
        segs[i].l = read(); segs[i].r = read(); 
        segs[i].id = i;
        lisan.push_back(segs[i].l); lisan.push_back(segs[i].r);
    } std::sort(ALL(lisan)); lisan.erase(std::unique(ALL(lisan)), lisan.end());
    cnt = (int) lisan.size();
    rep (i, 1, n) {
        segs[i].l = std::lower_bound(ALL(lisan), segs[i].l) - lisan.begin() + 1;
        segs[i].r = std::lower_bound(ALL(lisan), segs[i].r) - lisan.begin() + 1;
    }
    std::sort(segs + 1, segs + 1 + n, cmp);

    for (int i = 1; i <= n; ++i) {
        ans[segs[i].id] = bit.qrg(segs[i].l, segs[i].r);
        bit.mod(segs[i].l);
    }
    rep (i, 1, n) printf("%d\n", ans[i]);
    return 0;
}

E. Pursuit for Artifacts

Tarjan 杂题选讲

F

我看不懂题解,这下脑子真生锈了

posted @ 2021-11-02 14:58  Handwer  阅读(47)  评论(0编辑  收藏  举报