2017全国多校第9场

一、HDU-6162 Ch’s gift

思路:只要把主席树节点统计个数的意义改为累计所管辖区间的和就行了。剩下的部分就是裸的树上主席树了。

#include<bits/stdc++.h>
using namespace std;
#define MAXN 100010
#define LOGN 20
#define MAXQ 100010
#define LL long long
typedef struct {
    int to, next;
} Edge;
LL v[MAXN], dv[MAXN * 3], n, q, dvcnt;
LL par[MAXN][LOGN], depth[MAXN];
Edge edges[MAXN * 2];
int head[MAXN], ecnt;

void init() {
    memset(head, -1, sizeof(head));
    ecnt = 0;
    dvcnt = 0;
}

void add(int from, int to) {
    edges[ecnt].to = to;
    edges[ecnt].next = head[from];
    head[from] = ecnt++;
}

void dfs4lca(int root, int f) {
    par[root][0] = f, depth[root] = depth[f] + 1;
    for(int i = head[root]; ~i; i = edges[i].next) {
        int to = edges[i].to;
        if(to != f)dfs4lca(to, root);
    }
}

void prepare4lca() {
    dfs4lca(1, 0);
    for(int d = 0; d + 1 < LOGN; ++d) {
        for(int i = 1; i <= n; ++i) {
            if(par[i][d] == 0)par[i][d + 1] = 0;
            else par[i][d + 1] = par[par[i][d]][d];
        }
    }
}

int lca(int a, int b) {
    if(depth[a] < depth[b])swap(a, b);
    for(int i = LOGN - 1; i >= 0; i--) {
        int dif = depth[a] - depth[b];
        if((dif >> i) & 1)a = par[a][i];
    }
    if(a == b)return a;
    for(int i = LOGN - 1; i >= 0; --i) {
        if(par[a][i] != par[b][i]) {
            a = par[a][i], b = par[b][i];
        }
    }
    return par[a][0];
}

typedef struct {
    struct Node {
        int lch, rch;
        LL val;
    } nodes[MAXN * 20];
    int root[MAXN], ncnt;

    void init() {
        memset(nodes, 0, sizeof(nodes));
        memset(root, 0, sizeof(root));
        ncnt = 0;
    }
private:
    void update0(int& croot, int proot, LL val, int idx, int l, int r) {
        if(croot == 0) {
            croot = ++ncnt;
            nodes[croot].val = nodes[proot].val + val;
        }
        if(l == r)return;
        int mid = (l + r) >> 1;
        if(idx <= mid) {
            nodes[croot].rch = nodes[proot].rch;
            update0(nodes[croot].lch, nodes[proot].lch, val, idx, l, mid);
        } else {
            nodes[croot].lch = nodes[proot].lch;
            update0(nodes[croot].rch, nodes[proot].rch, val, idx, mid + 1, r);
        }
    }
public:
    void insert(int x, LL val, int idx) {
        update0(root[x], root[par[x][0]], val, idx, 1, dvcnt);
    }
private:
    LL query0(int qlrt, int qrrt, int da, int db, int l, int r) {
        if(l >= da && r <= db)return nodes[qrrt].val - nodes[qlrt].val;
        int mid = (l + r) >> 1;
        LL res = 0;
        if(da <= mid)res += query0(nodes[qlrt].lch, nodes[qrrt].lch, da, db, l, mid);
        if(db > mid)res += query0(nodes[qlrt].rch, nodes[qrrt].rch, da, db, mid + 1, r);
        return res;
    }
public:
    LL query(int ql, int qr, int da, int db, bool left_close) {
//        printf("%d %d\n", ql, par[ql][0]);
        if(left_close)return query0(root[par[ql][0]], root[qr], da, db, 1, dvcnt);
        else return query0(root[ql], root[qr], da, db, 1, dvcnt);
    }
} PerSegTree;

struct qqq {
    int ql, qr, a, b;
} qs[MAXQ];

#define indexOf(x) (lower_bound(dv + 1, dv + dvcnt + 1, x) - dv)
PerSegTree pst;
void buildPST(int root, int f) {
    pst.insert(root, v[root], indexOf(v[root]));
    for(int i = head[root]; ~i; i = edges[i].next) {
        int to = edges[i].to;
        if(to != f)buildPST(to, root);
    }
}

template<class T> inline void read(T& x) {
    bool s = 0;
    char t;
    while((t = getchar()) != ‘-‘ && (t < ‘0‘ || t > ‘9‘));
    if(t == ‘-‘)s = 1, t = getchar();
    x = t - ‘0‘;
    while((t = getchar()) >= ‘0‘ && t <= ‘9‘)x = x * 10 + (t ^ 48);
    if(s)x = -x;
}

int main() {
//    freopen("hdu6162.in", "r", stdin);
    int a, b;
    while(cin >> n >> q) {
        pst.init();
        init();
        for(int i = 1; i <= n; ++i)read(v[i]), dv[++dvcnt] = v[i];
        for(int i = 1; i < n; ++i) {
            read(a), read(b);
            add(a, b);
            add(b, a);
        }
        for(int i = 1; i <= q; ++i) {
            read(qs[i].ql), read(qs[i].qr), read(qs[i].a), read(qs[i].b);
            dv[++dvcnt] = qs[i].a;
            dv[++dvcnt] = qs[i].b;
        }
        prepare4lca();
        sort(dv + 1, dv + dvcnt + 1);
        dvcnt = unique(dv + 1, dv + dvcnt + 1) - dv;
        buildPST(1, 0);
        for(int i = 1; i <= q; ++i) {
            int s = qs[i].ql, t = qs[i].qr;
            int ilca = lca(s, t);
            LL sum = pst.query(ilca, s, indexOf(qs[i].a), indexOf(qs[i].b), 1)
                     + pst.query(ilca, t, indexOf(qs[i].a), indexOf(qs[i].b), 0);
            cout << sum << (i == q ? ‘\n‘ : ‘ ‘);
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/dowhile0/p/9222609.html

时间: 2024-10-17 19:55:08

2017全国多校第9场的相关文章

2017 全国多校第十场 训练日志

solve 2(310 / 634) J题题意搞错一口大锅. dzcH题结论猜对了,只是树上二分图不用匈牙利算法,能换成更高效的写法. B Array Challenge 高斯消元 + 矩阵快速幂 H Monkeys 二分图结论 J Schedule 优先队列 <qj> 题意: 有n个任务,给你开始时间和结束时间,有无数台机器,每台机器可以在同一时间最多处理一个任务,并且开机之后,只能关一次机,不能中途关机又开机. 问至少需要多少机器,在这么多台机器的情况下,最少花费多少.(花费 = 每台机器

2017年校招全国统一模拟笔试(第二场)编程题集合-牛客网

 2017年校招全国统一模拟笔试(第二场)编程题集合-牛客网 链接:https://www.nowcoder.com/questionTerminal/276712b113c6456c8cf31c5073a4f9d7来源:牛客网 牛牛有两个字符串(可能包含空格),牛牛想找出其中最长的公共连续子串,希望你能帮助他,并输出其长度. 输入描述: 输入为两行字符串(可能包含空格),长度均小于等于50. 输出描述: 输出为一个整数,表示最长公共连续子串的长度. 输入例子: abcde abgde 输出例子

【题集】牛客网&#183;2018年全国多校算法寒假训练营练习比赛(第二场)

原文链接:2018年全国多校算法寒假训练营练习比赛(第二场) A 吐泡泡 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32768K,其他语言65536K64bit IO Format: %lld 题目描述 小鱼儿吐泡泡,嘟嘟嘟冒出来.小鱼儿会吐出两种泡泡:大泡泡"O",小泡泡"o". 两个相邻的小泡泡会融成一个大泡泡,两个相邻的大泡泡会爆掉. (是的你没看错,小气泡和大气泡不会产生任何变化的,原因我也不知道.) 例如:ooOOoooO经过一段时间

2017全国两会政府工作报告(全文)

2017全国两会政府工作报告(全文) "两会"并不是一个特定的机构名称,而是对自1959年以来历年召开的"中华人民共和国全国人民代表大会"和"中国人民政治协商会议"的统称.由于两场会议会期基本重合,而且对于国家运作的重要程度都非常的高,故简称做"两会".下面一起来阅读2017年政府两会工作报告! 2017年两会政府工作报告 --2017年3月5日在第十二届全国人民代表大会第五次会议上 国务院总理 李克强 各位代表,现在,我代表

2014多校第十场1004 || HDU 4974 A simple water problem

题目链接 题意 : n支队伍,每场两个队伍表演,有可能两个队伍都得一分,也可能其中一个队伍一分,也可能都是0分,每个队伍将参加的场次得到的分数加起来,给你每个队伍最终得分,让你计算至少表演了几场. 思路 : ans = max(maxx,(sum+1)/2) :其实想想就可以,如果所有得分中最大值没有和的一半大,那就是队伍中一半一半对打,否则的话最大的那个就都包了. 1 #include <cstdio> 2 #include <cstring> 3 #include <st

多校第八场:图论出度

HDU 4948 这题比赛的时候遗憾了,我看了这道题,然后觉得挺简单的. 刚开始一看题上,想到的就是拓扑排序,然后脑子想啊想--感觉就是拓扑排序的逆序,然后发现挺水的-- 因为说了要想发展某个城市的话,就必须有另一个城市作为它发展的前提,即城市u->w这样连边,表示要想发展城市w,前提是u已经是发展过的城市了.那这样的话不是很简单嘛. 即统计出出度最多的就是第一个要发展的城市了,因为u->w这样连边可以看出算出出度最多的依次从大到小排序就行了. 哎呀,不过可惜了,因为看见没人交这题,然后也不敢

多校第六场 HDU 4927 JAVA大数类

题目大意:给定一个长度为n的序列a,每次生成一个新的序列,长度为n-1,新序列b中bi=ai+1?ai,直到序列长度为1.输出最后的数. 思路:这题实在是太晕了,比赛的时候搞了四个小时,从T到WA,唉--对算组合还是不太了解啊,现在对组合算比较什么了-- import java.io.*; import java.math.*; import java.util.*; public class Main { public static void main(String[] args) { Sca

2014 HDU多校弟八场H题 【找规律把】

看了解题报告,发现看不懂 QAQ 比较简单的解释是这样的: 可以先暴力下达标,然后会发现当前数 和 上一个数 的差值是一个 固定值, 而且等于当前数与i(第i个数)的商, 于是没有规律的部分暴力解决,有规律的套公式 //#pragma comment(linker, "/STACK:16777216") //for c++ Compiler #include <stdio.h> #include <iostream> #include <cstring&g

2014多校第七场1005 || HDU 4939 Stupid Tower Defense (DP)

题目链接 题意 :长度n单位,从头走到尾,经过每个单位长度需要花费t秒,有三种塔: 红塔 :经过该塔所在单位时,每秒会受到x点伤害. 绿塔 : 经过该塔所在单位之后的每个单位长度时每秒都会经受y点伤害. 蓝塔 : 经过该塔所在单位之后,再走每个单位长度的时候时间会变成t+z. 思路 : 官方题解 : 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #define LL long long