2019ccpc网络赛

B:https://acm.hdu.edu.cn/search.php?field=problem&key=2019�й���ѧ���������ƾ�����CCPC��+-+����ѡ����&source=1&searchmode=source
查询操作询问大于等于 \(k\) 且不在区间\([1, r]\)中 的最小值,强制在线,每个值都不同且范围在 \(1, n\),修改操作单点修改某个值为无穷
询问就是 下标\([r + 1, n + 1]\)\(val >= k\) 和 下标\([1, r]\)\((val >= k 且 修改过)\) 的最小值,显然最大只能是 \(n + 1\) 一定大于\(k\)
对于修改操作可以看作将原本pos 变为 无穷,值域线段树 ask(1, n + 1)值域中val > r && l >= k的最小值,
维护区间最右端点位置最大值,树上二分

const int maxn = 1e5 + 10;
int a[maxn], p[maxn];
struct seg{
    int t[maxn << 2];
    #define lr rt << 1
    #define rr rt << 1 | 1
    #define mid (l + r >> 1)
    #define root 1, 1, n
    #define lson lr, l, mid
    #define rson rr, mid + 1, r

    void push(int rt) {
        t[rt] = max(t[lr], t[rr]);
    }

    void build(int rt, int l, int r) {
        if(l == r) {
            t[rt] = p[l];
            return ;
        }
        build(lson);    build(rson);
        push(rt);
    }

    int query(int rt, int l, int r, int R, int k) {
        if(l == r)  return l;
        else if(k > mid) {
            if(t[rr] > R)    return query(rson, R, k);
            else return 0x3f3f3f3f;
        }
        else {
            int res = 0x3f3f3f3f;
            if(t[lr] > R)    res = query(lson, R, k);
            if(res == 0x3f3f3f3f && t[rr] > R)    res = query(rson, R, k);
            return res;
        }
    }

    void update(int rt, int l, int r, int x) {
        if(l == r)  {
            t[rt] = 0x3f3f3f3f;
            return ;
        }
        if(x <= mid)    update(lson, x);
        else    update(rson, x);
        push(rt);
    }
}T;

void run() {
    int n, m, lastans = 0;
    cin >> n >> m;
    for(int i = 1; i <= n; ++ i)    cin >> a[i], p[a[i]] = i;
    n ++; p[n] = n;
    T.build(root);
    for(int i = 1; i <= m; ++ i) {
        int op; cin >> op;
        if(op == 1) {
            int pos; cin >> pos;
            pos ^= lastans;
            if(a[pos]) T.update(root, a[pos]), a[pos] = 0;
        }
        else {
            int r, k;   cin >> r >> k;
            r ^= lastans; k ^= lastans;
            lastans = T.query(root, r, k);
            cout << lastans << '\n';
        }
    }
    return ;
}

D:
求图中第 \(k\) 小的路径长度
bfs,贪心的找,因为是有向边,对每个点所连边权排序,那么一开始最小的一定是某条边,接下来考虑下一条边的可能,1是可能非这条边拓展来的,那么就在原来的优先队列中,2是这条边拓展来的,那么可能就是当前边\(e(u, v)\),v拓展最小边权的边或者u返回拿取第二小的边,那么通过结构体记录当前拿的是u的第几小的边,每次出边就加两条边进去就行了

const int maxn = 5e4 + 10;
vector<pair<int, int>> g[maxn];
struct node{
    int u, v, nxt;
    ll val;
    node(int u, int v, int nxt, ll val) : u(u), v(v), nxt(nxt), val(val){}
    bool operator < (const node &a) const {
        return val > a.val;
    }
};

int ask[maxn], mx = 0, n, m, q;
ll ans[maxn];
void bfs() {
    priority_queue<node> q; int sz = 0;
    for(int i = 1; i <= n; ++ i)
        if(g[i].size()) q.push({i, g[i][0].second, 0, g[i][0].first});
    while(!q.empty()) {
        node top = q.top();
        q.pop();
        ans[++ sz] = top.val;
        if(sz == mx)    return ;
        int u = top.u, v = top.v;
        if(g[v].size()) q.push({v, g[v][0].second, 0, g[v][0].first + top.val});
        if(top.nxt + 1 < g[u].size())   q.push({u, g[u][top.nxt + 1].second, top.nxt + 1, g[u][top.nxt + 1].first + top.val - g[u][top.nxt].first});
    }
    return ;
}

void run() {
    mx = 0;
    cin >> n >> m >> q;
    for(int i = 1; i <= n; ++ i)    g[i].clear();
    for(int i = 1; i <= m; ++ i) {
        int u, v, w;
        cin >> u >> v >> w;
        g[u].push_back({w, v});
    }
    for(int i = 1; i <= n; ++ i)    sort(g[i].begin(), g[i].end());
    for(int i = 1; i <= q; ++ i)    cin >> ask[i], mx = max(mx, ask[i]);
    bfs();
    for(int i = 1; i <= q; ++ i)
        cout << ans[ask[i]] << '\n';
    return ;
}
posted @ 2021-08-27 11:26  wlhp  阅读(38)  评论(0)    收藏  举报