线段树+二分 80pts 求调
查看原帖
线段树+二分 80pts 求调
501865
TheSky233楼主2024/11/26 18:33

线段树+二分的做法,思路是维护可用时间的最小值,80pts,看了一圈没有这个分数的,求调 /bx

Record

#include <bits/stdc++.h>
#define F(i, a, b) for(int (i)=(a); (i)<=(b); ++(i))
#define int long long
using namespace std;

const int N = 2e5 + 5;

void read(int &x) {
    x = 0; char ch = getchar(); bool f = 0;
    while(!isdigit(ch)) f|=(ch=='-'), ch=getchar();
    while(isdigit(ch)) x=x*10+ch-'0', ch=getchar();
    x=f?-x:x;
}

struct node {
    int id, st, t;
    bool operator< (const node rhs) const{
        return st < rhs.st;
    }
}e[N];

int n, m;

struct segmentTree{
    int l, r;
    int Min;
}tree[N << 2];

void pushup(int p) {
    tree[p].Min = min(tree[p << 1].Min, tree[p << 1 | 1].Min);
}

void build(int p, int l, int r) {
    tree[p].l = l; tree[p].r = r;
    if(l == r) return;
    int mid = (l + r) >> 1;
    build(p << 1, l, mid);
    build(p << 1 | 1, mid + 1, r);
}

void update(int p, int x, int delta) {
    if(tree[p].l > x || tree[p].r < x) return;
    if(x == tree[p].l && tree[p].r == x) {
        tree[p].Min = delta;
        return;
    }
    int mid = (tree[p].l + tree[p].r) >> 1;
    update(p << 1, x, delta);
    update(p << 1 | 1, x, delta);
    pushup(p);
}

int query(int p, int L, int R) {
    if(L > tree[p].r || R < tree[p].l) {
        return 0;
    }
    if(L <= tree[p].l && tree[p].r <= R) {
        return tree[p].Min;
    }
    int ans = 2147483647;
    int mid = (tree[p].l + tree[p].r) >> 1;
    if(L <= mid) ans = min(ans, query(p << 1, L, R));
    if(R > mid) ans = min(ans, query(p << 1 | 1, L, R));
    pushup(p);
    return ans;
}

vector<int> v[N];

signed main() {
//    freopen("print.in", "r", stdin);
//    freopen("print.out", "w", stdout);
    read(n); read(m);
    F(i, 1, n) {
        int st, t;
        read(t); read(st);
        e[i] = {i, st, t};
    }
    sort(e + 1, e + n + 1);
    build(1, 1, m);
    F(i, 1, n) {
        int l = 1, r = m;
        bool f = 0;
        while(l <= r) {
            int mid = (l + r) >> 1;
            if(query(1, 1, mid) <= e[i].st) {
                r = mid - 1; f = 1;
            }
            else l = mid + 1;
        }
        if(f == 0) { // 无可用的,找可用时间的最小值
            int Max = query(1, 1, m);
            int l = 1, r = m, ans = 0;
            while(l <= r) {
                int mid = (l + r) >> 1;
                if(query(1, 1, mid) > Max) {
                    l = mid + 1;
                }
                else r = mid - 1, ans = mid;
            }
            update(1, ans, Max + e[i].t);
            v[ans].push_back(e[i].id);
        }
        else { // 有可用的
            update(1, l, e[i].st + e[i].t);
            v[l].push_back(e[i].id);
        }
    }
    F(i, 1, m) {
        cout << v[i].size() << ' ';
        sort(v[i].begin(), v[i].end());
        for(auto it : v[i]) {
            cout << it << ' ';
        }
        cout << '\n';
    }
}
2024/11/26 18:33
加载中...