• bzoj4009


    4009: [HNOI2015]接水果

    Time Limit: 60 Sec  Memory Limit: 512 MB
    Submit: 633  Solved: 299
    [Submit][Status][Discuss]

    Description

    风见幽香非常喜欢玩一个叫做 osu!的游戏,其中她最喜欢玩的模式就是接水果。
    由于她已经DT FC 了The big black,  她觉得这个游戏太简单了,于是发明了一个更
    加难的版本。首先有一个地图,是一棵由 n 个顶点、n-1 条边组成的树(例如图 1
    给出的树包含 8 个顶点、7 条边)。这颗树上有 P 个盘子,每个盘子实际上是一条
    路径(例如图 1 中顶点 6 到顶点 8 的路径),并且每个盘子还有一个权值。第 i 个
    盘子就是顶点a_i到顶点b_i的路径(由于是树,所以从a_i到b_i的路径是唯一的),
    权值为c_i。接下来依次会有Q个水果掉下来,每个水果本质上也是一条路径,第
    i 个水果是从顶点 u_i 到顶点v_i 的路径。幽香每次需要选择一个盘子去接当前的水
    果:一个盘子能接住一个水果,当且仅当盘子的路径是水果的路径的子路径(例如
    图1中从 3到7 的路径是从1到8的路径的子路径)。这里规定:从a 到b的路径与
    从b到 a的路径是同一条路径。当然为了提高难度,对于第 i 个水果,你需要选择
    能接住它的所有盘子中,权值第 k_i 小的那个盘子,每个盘子可重复使用(没有使用次数
    的上限:一个盘子接完一个水果后,后面还可继续接其他水果,只要它是水
    果路径的子路径)。幽香认为这个游戏很难,你能轻松解决给她看吗? 
     

    Input

    第一行三个数 n和P 和Q,表示树的大小和盘子的个数和水果的个数。 

    接下来n-1 行,每行两个数 a、b,表示树上的a和b 之间有一条边。树中顶点
    按1到 n标号。 接下来 P 行,每行三个数 a、b、c,表示路径为 a 到 b、权值为 c 的盘子,其
    中0≤c≤10^9,a不等于b。 
    接下来Q行,每行三个数 u、v、k,表示路径为 u到 v的水果,其中 u不等于v,你需要选择第 k小的盘子,
    第k 小一定存在。 
     

    Output

     对于每个果子,输出一行表示选择的盘子的权值。 

    Sample Input

    10 10 10
    1 2
    2 3
    3 4
    4 5
    5 6
    6 7
    7 8
    8 9
    9 10
    3 2 217394434
    10 7 13022269
    6 7 283254485
    6 8 333042360
    4 6 442139372
    8 3 225045590
    10 4 922205209
    10 8 808296330
    9 2 486331361
    4 9 551176338
    1 8 5
    3 8 3
    3 8 4
    1 8 3
    4 8 1
    2 3 1
    2 3 1
    2 3 1
    2 4 1
    1 4 1

    Sample Output

    442139372
    333042360
    442139372
    283254485
    283254485
    217394434
    217394434
    217394434
    217394434
    217394434

    HINT

    N,P,Q<=40000。 

    Source

    http://blog.csdn.net/thy_asdf/article/details/50363672

    前面的部分说的很详细了。但是写的时候要注意几点:

    1. 判断lca类型的时候u和v比较的是dfn大小,不是dep大小

    2.水果读入的时候如果dfn[x1] > dfn[y1] swap(x1, y1)

    3.整体二分里排序注意插入删除和水果的顺序

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 100010;
    int n, p, m, cnt, tot = 1, Time;
    struct E {
        int nxt, to;
    } e[N << 1];
    struct P {
        int x1, y1, x2, y2, w, id, k, type;
        P(int x1 = 0, int y1 = 0, int x2 = 0, int y2 = 0, int w = 0, int id = 0, int k = 0, int type = 0) : x1(x1), y1(y1), x2(x2), y2(y2), w(w), id(id), k(k), type(type) {}
    } event[N], q[N];
    struct BIT {
        int tree[N];
        int lowbit(int x) {return x&(-x);}
        void update(int l, int r, int v) 
        {
            for(int i = l; i <= n; i += lowbit(i)) tree[i] += v;
            for(int i = r + 1; i <= n; i += lowbit(i)) tree[i] -= v;
        }
        int query(int pos) {int ret = 0; for(int i = pos; i; i -= lowbit(i)) ret += tree[i]; return ret;}
    } t;
    vector<P> c, lp, rp; 
    int head[N], ans[N], low[N], dfn[N] ,fa[23][N], dep[N];
    void link(int u, int v)
    {
        e[++tot].nxt = head[u];
        head[u] = tot;
        e[tot].to = v;
    }
    bool cp(P i, P j) {return i.w < j.w;} 
    bool cp1(P i, P j) {return i.x1 == j.x1 ? i.type < j.type : i.x1 < j.x1;}
    void dfs(int u, int last)
    {
        dfn[u] = ++Time;
        for(int i = head[u]; i; i = e[i].nxt) if(e[i].to != last)
        {
            fa[0][e[i].to] = u;
            dep[e[i].to] = dep[u] + 1;
            dfs(e[i].to, u);
        }
        low[u] = Time;
    }
    int lca(int u, int v)
    {
        if(dep[u] < dep[v]) swap(u, v);
        for(int i = 22; i >= 0; --i) if((dep[u] - dep[v]) & (1 << i))
            u = fa[i][u];
        if(u == v) return u;
        for(int i = 22; i >= 0; --i) if(fa[i][u] != fa[i][v])
        {
            u = fa[i][u]; v = fa[i][v];
        }
        return fa[0][u];
    }
    int jump(int u, int h)
    {
        for(int i = 22; i >= 0; --i) if(h & (1 << i)) u = fa[i][u]; return u;
    }
    void solve(int l, int r, int lb, int rb)
    {
        if(l > r) return;
        if(lb == rb)
        {
            for(int i = l; i <= r; ++i) ans[q[i].id] = event[lb].w;
            return;
        }
        int mb = (lb + rb) >> 1;
        c.clear(); lp.clear(); rp.clear();
        for(int i = lb; i <= mb; ++i)
        {//盘子 
            P x = event[i]; 
    //        printf("x1=%d x2=%d
    ", x.x1, x.x2);
            x.w = 1; x.type = 0;
            c.push_back(x); x.type = 2;
            x.w = -1; x.x1 = event[i].x2;
            c.push_back(x);            
        }
        for(int i = l; i <= r; ++i)
        {//水果 
            c.push_back(q[i]);
        }
        sort(c.begin(), c.end(), cp1);
        for(int i = 0; i < c.size(); ++i)
        {
            if(c[i].type != 1) 
            {
    //            printf("x=%d y1=%d y2=%d
    ", c[i].x1, c[i].y1, c[i].y2);
                t.update(c[i].y1, c[i].y2, c[i].w);
            } 
            else 
            {
                int sum = t.query(c[i].y1);
    //            printf("sum=%d k=%d
    ", sum, c[i].k);
                if(sum >= c[i].k) lp.push_back(c[i]);
                else {c[i].k -= sum; rp.push_back(c[i]);}
            }
        }
        for(int i = 0; i < c.size(); ++i) if(c[i].type != 1)
            t.update(c[i].y1, c[i].y2, -c[i].w);
        for(int i = 0; i < lp.size(); ++i) q[l + i] = lp[i];
        for(int i = 0; i < rp.size(); ++i) q[l + lp.size() + i] = rp[i];
        int mid = l + lp.size() - 1;
        solve(l, mid, lb, mb); solve(mid + 1, r, mb + 1, rb);
    }
    int main()
    {
        freopen("fruit_hnoi2015.in", "r", stdin);
        freopen("fruit_hnoi2015.out", "w", stdout);
        scanf("%d%d%d",&n,&p,&m);
        for(int i = 1; i < n; ++i)
        {
            int u, v; scanf("%d%d",&u,&v);
            link(u, v); link(v, u);
        }
        memset(fa, -1, sizeof(fa));
        dfs(1, 0);
        for(int i = 1; i <= 22; ++i)
            for(int j = 1; j <= n; ++j) if(fa[i-1][j] != -1)
                fa[i][j] = fa[i-1][fa[i-1][j]];
        for(int i = 1; i <= p; ++i)
        {
            int u, v, w; scanf("%d%d%d", &u, &v, &w);
            int x = lca(u, v);
            if(dfn[u] > dfn[v]) swap(u, v);
            if(u != x) 
            {
                event[++cnt].x1 = dfn[u]; event[cnt].y1 = dfn[v];
                event[cnt].x2 = low[u]; event[cnt].y2 = low[v]; 
                event[cnt].w = w; 
            }
            else
            {
                int t = jump(v, dep[v] - dep[u] - 1);
                event[++cnt].x1 = 1; event[cnt].y1 = dfn[v];
                event[cnt].x2 = dfn[t] - 1; event[cnt].y2 = low[v];
                event[cnt].w = w;
                if(low[t] < n)
                {
                    event[++cnt].x1 = dfn[v]; event[cnt].y1 = low[t] + 1;
                    event[cnt].x2 = low[v]; event[cnt].y2 = n;
                    event[cnt].w = w; 
                }
            }
        }
        for(int i = 1; i <= m; ++i)
        {
            int u, v;
            scanf("%d%d%d", &u, &v, &q[i].k);
            if(dfn[u] > dfn[v]) swap(u, v);
            q[i].x1 = dfn[u]; q[i].y1 = dfn[v];
            q[i].id = i; q[i].type = 1;
        }
        sort(event + 1, event + cnt + 1, cp);
        solve(1, m, 1, cnt);
        for(int i = 1; i <= m; ++i) printf("%d
    ", ans[i]);
        fclose(stdin); fclose(stdout);
        return 0;
    }
    View Code
  • 相关阅读:
    一些你可能用到的代码
    iOS 键盘下去的方法
    iOS设计模式汇总
    随笔
    Spring cloud config 分布式配置中心 (三) 总结
    Spring cloud config 分布式配置中心(二) 客户端
    Spring cloud config 分布式配置中心(一) 服务端
    jdbcUrl is required with driverClassName spring boot 2.0版本
    JpaRepository接口找不到 spring boot 项目
    解决IntelliJ “Initialization failed for 'https://start.spring.io'
  • 原文地址:https://www.cnblogs.com/19992147orz/p/6579675.html
Copyright © 2020-2023  润新知