zoukankan      html  css  js  c++  java
  • 大富翁 线段树+二分 +dfs

    https://csustacm.fun/problem/2033

    这个题目还是比较简单的,但是比赛的时候没有像清楚,用了一个不太熟悉的数据结构主席树,

    所以出现了bug,主席树的bug是真的难找。

    这个题目就是首先用dfs+线段树求出每一个富翁的val

    然后用二分加线段树来找位置。

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <queue>
    #include <algorithm>
    #include <iostream>
    #define inf 0x3f3f3f3f
    using namespace std;
    const int maxn = 1e5 + 10;
    typedef long long ll;
    ll a[maxn], lazy[maxn * 4], sum[maxn * 4], flag[maxn * 4];
    int n, val[maxn];
    vector<int>G[maxn];
    void add(int u, int v) {
        G[u].push_back(v);
        G[v].push_back(u);
    }
    
    void push_down(int id,int l,int r) {
        if (lazy[id] == 0) return;
        // printf("ss id=%d l=%d r=%d
    ", id, l, r);
        int mid = (l + r) >> 1;
        if (flag[id << 1]) {
            // printf("id=%d l=%d r=%d
    ", id, l, r);
            sum[id << 1] += (mid - l + 1)*lazy[id];
            lazy[id << 1] += lazy[id];
        }
        if (flag[id << 1 | 1]) {
            // printf("ww id=%d l=%d r=%d
    ", id, l, r);
            sum[id << 1 | 1] += (r - mid)*lazy[id];
            lazy[id << 1 | 1] += lazy[id];
        }
        lazy[id] = 0;
    }
    
    void update1(int id, int l, int r, int pos,int f) {
        if (pos<l || pos>r) return;
        if (f == 0) flag[id]++;
        else if (f == 1)flag[id]--;
        if (l == r) {
            sum[id] = 1;
            return;
        }
        push_down(id, l, r);
        int mid = (l + r) >> 1;
        if (pos <= mid) update1(id << 1, l, mid, pos, f);
        else update1(id << 1 | 1, mid + 1, r, pos, f);
        sum[id] = sum[id << 1] + sum[id << 1 | 1];
    }
    
    void update2(int id,int l,int r,int x,int y)
    {
        // printf("id=%d l=%d r=%d x=%d y=%d
    ", id, l, r, x, y);
        if (x > r || y < l) return;
        if (x <= l && y >= r) {
            lazy[id] += 1;
            sum[id] += (r - l + 1);
            return;
        }
        push_down(id, l, r);
        int mid = (l + r) >> 1;
        if (x <= mid) update2(id << 1, l, mid, x, y);
        if (y > mid) update2(id << 1 | 1, mid + 1, r, x, y);
        sum[id] = sum[id << 1] + sum[id << 1 | 1];
    }
    
    int query(int id,int l,int r,int pos)
    {
        if (pos<l || pos>r) return 0;
        if (l == r) return sum[id];
        push_down(id, l, r);
        int mid = (l + r) >> 1;
        if (pos <= mid) return query(id << 1, l, mid, pos);
        return query(id << 1 | 1, mid + 1, r, pos);
    }
    
    void dfs(int u, int pre) {
        // printf("u=%d a=%lld
    ", u, a[u]);
        update2(1, 1, n, 1, a[u]);
        update1(1, 1, n, a[u], 0);
        for (int i = 0; i < G[u].size(); i++) {
            int v = G[u][i];
            if (v == pre) continue;
            dfs(v, u);
            val[a[u]] = min(val[a[u]], query(1, 1, n, a[u]));
            // printf("val[%lld]=%d v=%d
    ", a[u], val[a[u]], v);
            update1(1, 1, n, a[u], 2);
        }
        update1(1, 1, n, a[u], 1);
    }
    
    int c[maxn];
    
    int lowbit(int x)
    {
        return x & (-x);
    }
    
    void update(int x,int k)
    {
        while (x <= n) {
            c[x] += k;
            x += lowbit(x);
        }
    }
    
    int getsum(int x)
    {
        int ans = 0;
        while (x > 0) {
            ans += c[x];
            x -= lowbit(x);
        }
        return ans;
    }
    
    int main() {
        int x;
        scanf("%d", &n);
        memset(val, inf, sizeof(val));
        for (int i = 1; i <= n; i++) scanf("%d", &x), a[x] = i, G[i].clear();
        for (int i = 1; i < n; i++) {
            int u, v;
            scanf("%d%d", &u, &v);
            add(u, v);
        }
        dfs(1, -1);
        for (int i = 1; i <= n; i++) if (val[i] >= inf) val[i] = 1;
        // for (int i = 1; i <= n; i++) printf("val[%d]=%d
    ", i, val[i]);
        for (int i = 1; i <= n; i++) {
            int l = 1, r = n, ans = 0;
            while (l <= r) {
                int mid = (l + r) >> 1;
                int res = mid - getsum(mid);
                if (res >= val[i]) ans = mid, r = mid - 1;
                else l = mid + 1;
            }
            printf("%d
    ", ans);
            update(ans, 1);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    P1847 轰炸II
    c++ 如何对拍
    P2689 东南西北
    P2006 赵神牛的游戏
    P1320 压缩技术(续集版)
    vuex
    less
    将二维数组转化成一维数组
    剩余数组(从'水果数组'筛选掉'吃了的数组')
    将一维数组转化成二维数组
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/11521250.html
Copyright © 2011-2022 走看看