2018-2019 ACM-ICPC Southeastern European Regional Programming Contest

和队友练习,拉了一套国外的区域赛题来做,写了两道题回寝室了,感觉还能够再过一题B的

E - Fishermen

n条鱼有每个鱼的x、y坐标,m个渔夫有m个x轴上的坐标,每个渔夫能钓到|a - x| + y <= l,其中a,b为鱼的坐标,x为渔夫的坐标,l是题目给出的鱼竿长度,求每个渔夫能钓到的鱼数
考虑预处理鱼或者渔夫,发现预处理鱼更简单,将鱼能被钓起来的x坐标左右端点预处理出来,然后对左端点大小排序。
然后渔夫可能输入是乱序的,我们也将渔夫坐标排序;现在就要考虑怎么维护每个渔夫能钓到鱼数量了,用一个小顶堆维护,每次加入鱼的左端点小于等于人的坐标,去判断右端点满足大于等于认得坐标,一次O(n)

#include 
using namespace std;

typedef long long ll;
const int maxn = 5e5;
struct fish {
    int l, r;
    fish() {}
    fish(int a, int b) : l(a), r(b) {}
    bool operator <(const fish& x) const {
        return l == x.l ? r < x.r : l < x.l;
    }
} F[maxn];
struct peo {
    int id, x;
    bool operator <(const peo& a) const {
        return x < a.x;
    }
} P[maxn];
priority_queue< int, vector, greater > que;
int ans[maxn];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n, m, l, x, y;
    cin >> n >> m >> l;
    for(int i = 1; i <= n; i++) {
        cin >> x >> y;
        if(y > l) F[i].l = F[i].r = 0;
        else {
            int L = max(0, x - (l - y)), R = min(1000000000, x + (l - y));
            F[i].l = L, F[i].r = R;
        }
    }
    sort(F + 1, F + 1 + n);
    for(int i = 1; i <= m; i++) {
        P[i].id = i;
        cin >> P[i].x;
    }
    sort(P + 1, P + 1 + m);
    int pos = 1;
    for(int i = 1; i <= m; i++) {
        while(F[pos].l <= P[i].x && pos <= n) {
            que.push(F[pos].r);
            pos++;
        }
        while(!que.empty() && que.top() < P[i].x) que.pop();
        ans[P[i].id] = que.size();
    }
    for(int i = 1; i <= m; i++) cout << ans[i] << '\n';
}

C - Tree

给出n个点的树,每个点有黑色(1)和白色(0)的颜色,让我们选出m个黑色的点使最远的两个黑点之间距离最近。
刚开始以为是树形dp,发现状态有点难得维护。队友给出二分思路,表示可以二分使满足点到点距离小于二分距离的点数量和m比较

#include 
using namespace std;

const int maxn = 105;
int st[maxn];
vector e[maxn];

int vis[maxn], n, m;
int dfs(int u, int pre, int k, int dfn) {
    int res = st[u];
    if(dfn == k) return res;
    for(int v : e[u]) {
        if(v == pre || !vis[v]) continue;
        res += dfs(v, u, k, dfn + 1);
    }
    return res;
}
bool cek(int k) {
    queue que;
    memset(vis, 0, sizeof(vis));
    que.push(1);
    while(!que.empty()) {
        int u = que.front();
        que.pop();
        vis[u] = 1;
        if(dfs(u, 0, k, 0) >= m) return 1;
        for(int v : e[u]) {
            if(vis[v]) continue;
            que.push(v);
        }
    }
    return 0;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> n >> m;
    for(int i = 1; i <= n; i++) cin >> st[i];
    for(int i = 1; i < n; i++) {
        int u, v;
        cin >> u >> v;
        e[u].emplace_back(v);
        e[v].emplace_back(u);
    }
    int l = 0, r = n;
    while(l < r) {
        int mid = l + r >> 1;
        if(cek(mid)) r = mid;
        else l = mid + 1;
    }
    cout << r << '\n';
}

你可能感兴趣的:(总结)