【分块】 HDU 4336 Successor

通道

题意:给一个树,树上每个节点都有两个属性:忠诚度和能力,给出若干查询,求每个子树中能力 > 树根能力的点中,忠诚度最高的那个

思路:子树dfs序即可,然后忠诚度排个序,取能力值大于u且忠诚度最高的,虽然线段树也可以搞,练练分块。

代码:

#pragma comment(linker, "/STACK:102400000,102400000")
#include <cstdio>
#include <vector>
#include <map>
#include <cstring>
#include <algorithm>

using namespace std;

typedef long long Long;

const int MAGIC = 250;
const int MAX_N = 50007;

struct staff {
    int loyalty, ability;
};

bool operator < (staff a,staff b) {
    return a.ability < b.ability;
}

vector<int> adj[MAX_N];
staff arr[MAX_N], list[MAX_N], sorted[MAX_N];
int pos[MAX_N], maxl[MAX_N], size[MAX_N];
map<int,int> rev;
int tot, n, q;

int dfs(int u) {
    pos[u] = tot;
    list[tot] = sorted[tot] = arr[u];
    tot++;
    int ret = 1;
    for (int i = 0; i < adj[u].size(); i++) {
        ret += dfs(adj[u][i]);
    }
    return size[pos[u]] = ret;
}

int work(int l,int r,int val) {
    if (sorted[r].ability <= val) return -1;
    if (sorted[l].ability > val) return maxl[l];
    while (l + 1 < r) {
        int mid = (l + r) >> 1;
        if (sorted[mid].ability > val) r = mid; else l = mid;
    }
    return maxl[r];
}

int main() {
    int T;
    scanf("%d",&T);
    while (T--) {
        scanf("%d%d",&n, &q);
        for (int i = 0; i < n; i++) {
            adj[i].clear();
            arr[i].loyalty = arr[i].ability = -1;
            sorted[i] = list[i] = arr[i];
        }
        memset(size, 0, sizeof size);
        memset(maxl, 0, sizeof maxl);
        memset(pos, 0, sizeof pos);
        rev.clear();
        rev[-1] = -1;
        for (int i = 1; i < n; i++) {
            int fa,l,a;
            scanf("%d%d%d",&fa,&l,&a);
            adj[fa].push_back(i);
            rev[arr[i].loyalty = l] = i;
            arr[i].ability = a;
        }
        tot = 0;
        dfs(0);
        for (int i = 0; i < n; i += MAGIC) {
            int j = i + MAGIC;
            if (j > n) break;
            sort(sorted + i, sorted + j);
            maxl[j - 1] = sorted[j - 1].loyalty;
            for (int k = j - 2; k >= i; k--)
                maxl[k] = max(maxl[k + 1], sorted[k].loyalty);
        }
        while (q--) {
            int st; scanf("%d",&st);
            int val = arr[st].ability;
            st = pos[st];
            int ed = st + size[st] - 1;
            int ans = -1;
            for (int i = st; i <= ed;) {
                if (i % MAGIC == 0 && i + MAGIC - 1 <= ed) {
                    int tmp = work(i, i + MAGIC - 1, val);
                    if (tmp > ans) ans = tmp;
                    i += MAGIC;
                } else {
                    if (list[i].ability > val && list[i].loyalty > ans) ans = list[i].loyalty;
                    i++;
                }
            }
            printf("%d\n",rev[ans]);
        }
    }
    return 0;
}

时间: 2024-10-28 10:11:09

【分块】 HDU 4336 Successor的相关文章

HDU 4336 Card Collector(动态规划-概率DP)

Card Collector Problem Description In your childhood, do you crazy for collecting the beautiful cards in the snacks? They said that, for example, if you collect all the 108 people in the famous novel Water Margin, you will win an amazing award. As a

hdu 4366 Successor - CDQ分治 - 线段树 - 树分块

Sean owns a company and he is the BOSS.The other Staff has one Superior.every staff has a loyalty and ability.Some times Sean will fire one staff.Then one of the fired man’s Subordinates will replace him whose ability is higher than him and has the h

HDU 4366 Successor 分块做法

http://acm.hdu.edu.cn/showproblem.php?pid=4366 今日重新做了这题的分块,果然是隔太久了,都忘记了.. 首先,用DFS序变成一维的问题 关键是它有两个权值,该如何处理呢? 首先假设我们的DFS序列是List, 那么,对其进行分块.对于每一个块,先按能力排序,用数组tosort[]保存,这样我就可以用O(magic)的时间,就是扫一次这个块,维护出一个数组,mx[i]表示大于等于tosort[i].ablity时,最大的忠诚度. 那么我查询的时候,就可以

HDU - 4366 Successor DFS序 + 分块暴力 or 线段树维护

给定一颗树,每个节点都有忠诚和能力两个参数,随意指定一个节点,要求在它的子树中找一个节点代替它,这个节点要满足能力值大于它,而且是忠诚度最高的那个. 首先,dfs一下,处理出L[i], R[i]表示dfs序,则R[i] - L[i] + 1 就是当前i这个节点拥有的子孙个数. 对于一颗树,dfs的时候,访问节点有先后顺序,那么可以用一个struct node List[maxn];表示这课树中访问的先后顺序. 例如这颗树,我假设是先访问0 --> 3 --> 2 ---> 4 ---&g

hdu 4336 Card Collector

Card Collector http://acm.hdu.edu.cn/showproblem.php?pid=4336 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Special Judge Problem Description In your childhood, do you crazy for collecting the beautiful cards in

HDU 4336:Card Collector 期望+状压

Card Collector 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4336 题意: 去商店里买零食,每包零食里最多有1张卡片,也有可能没有,问要集齐所有n(n≤20)种卡片所需要购买零食个数的期望. 题解: 设dp[i](二进制,对应位为1表示已经有该卡片)为以当前状态为起点还需要购买零食个数的期望,则dp[0]即答案 对DP求解期望有问题的可以看下这里 代码 #include<stdio.h>#include<string.h

HDU 4366 Successor

Successor Time Limit: 1000ms Memory Limit: 65536KB This problem will be judged on HDU. Original ID: 436664-bit integer IO format: %I64d      Java class name: Main Sean owns a company and he is the BOSS.The other Staff has one Superior.every staff has

hdu 4336 Card Collector(期望)

http://acm.hdu.edu.cn/showproblem.php?pid=4336 有N种卡片,每一袋零食里面最多有一张卡片,给出一袋零食里面每种卡片的概率,问平均要买多少袋零食能收集到所有的卡片. 状态压缩一下,共有1<<n-1个状态,设dp[sta]表示当前状态到目标状态平均买的零食数目,已知终态dp[1<<n-1] = 0,dp[sta]可由一下状态得到: 这一袋零食里没有卡片,概率为p(没有一张卡片的概率),状态转移到sta: 这一袋零食里面有卡片j,但是他已经拥

HDU 4336:Card Collector(容斥原理)

http://acm.split.hdu.edu.cn/showproblem.php?pid=4336 Card Collector Special Judge Problem Description In your childhood, do you crazy for collecting the beautiful cards in the snacks? They said that, for example, if you collect all the 108 people in