BZOJ 4012权限题

浙科协的网突然炸了,好慌……

据说正解是动态点分治,然而我并不会,我选择树链剖分 + 主席树维护。

设$dis_i$表示$i$到$root(1)$的值,那么对于一个询问$u$,答案为$\sum_{i = 1}^{n}dis_i + n * dis_u - 2 * \sum_{i = 1}^{n}dis_{lca(i, u)}$。

前两个东西很好维护,我们考虑如何维护后面这个$\sum$,对于每一个点我们可以把它到根跳一跳,然后把这个点对答案的贡献加到线段树中,如果再限定一个$[l, r]$的区间,只要把所有年龄排序从小到大排序按照贡献加到主席树中就可以了。

注意一条树链的贡献和线段树上区间的边界要搞清楚。

主席树标记永久化一下比较好,虽然感觉空间是开不下的,但是这题就这么过去了。

时间复杂度$O((n + q)log^2n)$。

Code:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll; const int N = 1.5e5 + ;
const int M = 1e7 + ;
const int inf = << ; int n, qn, tot = , head[N], dfsc = , dep[N];
int top[N], fa[N], siz[N], son[N], id[N];
ll P, dis[N], toVal[N], sumE[N], sumDis[N]; struct Edge {
int to, nxt;
ll val;
} e[N << ]; inline void add(int from, int to, ll val) {
e[++tot].to = to;
e[tot].val = val;
e[tot].nxt = head[from];
head[from] = tot;
} struct Item {
int age, id; friend bool operator < (const Item &x, const Item &y) {
if(x.age == y.age) return x.id < y.id;
else return x.age < y.age;
} } a[N]; template <typename T>
inline void read(T &X) {
X = ; char ch = ; T op = ;
for(; ch > '' || ch < ''; ch = getchar())
if(ch == '-') op = -;
for(; ch >= '' && ch <= ''; ch = getchar())
X = (X << ) + (X << ) + ch - ;
X *= op;
} inline void swap(int &x, int &y) {
int t = x; x = y; y = t;
} inline int max(int x, int y) {
return x > y ? x : y;
} inline int min(int x, int y) {
return x > y ? y : x;
} void dfs1(int x, int fat, int depth, ll nowDis) {
fa[x] = fat, dep[x] = depth;
siz[x] = , dis[x] = nowDis;
int maxson = -;
for(int i = head[x]; i; i = e[i].nxt) {
int y = e[i].to;
if(y == fat) continue;
dfs1(y, x, depth + , nowDis + e[i].val); toVal[y] = e[i].val;
siz[x] += siz[y]; if(siz[y] > maxson) {
maxson = siz[y];
son[x] = y;
}
}
} void dfs2(int x, int topf) {
top[x] = topf, sumE[id[x] = ++dfsc] = toVal[x];
if(!son[x]) return;
dfs2(son[x], topf);
for(int i = head[x]; i; i = e[i].nxt) {
int y = e[i].to;
if(y == fa[x] || y == son[x]) continue;
dfs2(y, y);
}
} namespace PSegT {
struct Node {
int lc, rc;
ll sum, cnt;
} s[M]; int root[N], nodeCnt = ; #define lc(p) s[p].lc
#define rc(p) s[p].rc
#define sum(p) s[p].sum
#define cnt(p) s[p].cnt
#define mid ((l + r) >> 1) void ins(int &p, int l, int r, int x, int y, int pre) {
s[p = ++nodeCnt] = s[pre];
if(x <= l && y >= r) {
++cnt(p);
return;
}
sum(p) += sumE[min(y, r)] - sumE[max(x, l) - ]; if(x <= mid) ins(lc(p), l, mid, x, y, lc(pre));
if(y > mid) ins(rc(p), mid + , r, x, y, rc(pre));
} ll query(int p, int l, int r, int x, int y) {
ll res = 1LL * cnt(p) * (sumE[min(y, r)] - sumE[max(x, l) - ]);
if(x <= l && y >= r) return res + sum(p); if(x <= mid) res += query(lc(p), l, mid, x, y);
if(y > mid) res += query(rc(p), mid + , r, x, y); return res;
} } using namespace PSegT; inline void modify(int rt, int x) {
for(; x; x = fa[top[x]])
ins(root[rt], , n, id[top[x]], id[x], root[rt]);
} inline ll solve(int rt, int x) {
ll res = 0LL;
for(; x; x = fa[top[x]])
res += query(root[rt], , n, id[top[x]], id[x]);
return res;
} int main() {
// freopen("Sample.txt", "r", stdin); read(n), read(qn), read(P);
for(int i = ; i <= n; i++) {
read(a[i].age);
a[i].id = i;
} for(int i = ; i < n; i++) {
int x, y; ll v;
read(x), read(y), read(v);
add(x, y, v), add(y, x, v);
}
dfs1(, , , 0LL), dfs2(, ); /* for(int i = 1; i <= n; i++)
printf("%d ", top[i]);
printf("\n"); */ sort(a + , a + + n);
for(int i = ; i <= n; i++) {
sumE[i] += sumE[i - ];
sumDis[i] = sumDis[i - ] + dis[a[i].id];
}
for(int i = ; i <= n; i++) {
root[i] = root[i - ];
modify(i, a[i].id);
} /* for(int i = 1; i <= n; i++)
printf("%lld ", sumE[i]);
printf("\n");
for(int i = 1; i <= n; i++)
printf("%lld ", sumDis[i]);
printf("\n"); */ ll ans = 0LL;
for(int x, l, r; qn--; ) {
read(x), read(l), read(r);
l = (1LL * l + ans) % P, r = (1LL * r + ans) % P;
if(l > r) swap(l, r); l = lower_bound(a + , a + + n, (Item) {l, }) - a;
r = upper_bound(a + , a + + n, (Item) {r, inf}) - a - ; ans = 1LL * (r - l + ) * dis[x] + sumDis[r] - sumDis[l - ] - 2LL * (solve(r, x) - solve(l - , x));
printf("%lld\n", ans);
} return ;
}

Luogu 3241 [HNOI2015]开店的更多相关文章

  1. luogu 3241 [HNOI2015]开店 动态点分治+二分+vector

    独立写出来+想出来的,1.5h就切了~ 建立点分树,然后用 $vector$ 暴力存所有子节点,然后二分一下子就可以了. #include <cstdio> #include <ve ...

  2. luogu P3241 [HNOI2015]开店

    传送门 (下面记年龄为\(a_x\))题目要求的是\[\sum_{x=1}^{n} [a_x\in [l,r]]*dis(x,u)=\sum_{x=1}^{n} [a_x\in [l,r]]*de_x ...

  3. [HNOI2015]开店 树链剖分,主席树

    [HNOI2015]开店 LG传送门 蒟蒻表示不会动态淀粉质. 先把点按年龄排序, 设\(dis[i]\)表示\(i\)到根的距离. 把我们要算的东西稍微变下形:\(ans\) \[ = \sum \ ...

  4. 洛谷 P3241 [HNOI2015]开店 解题报告

    P3241 [HNOI2015]开店 题目描述 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱. 这样的想法当然非 ...

  5. [BZOJ4012][HNOI2015]开店(动态点分治,树链剖分)

    4012: [HNOI2015]开店 Time Limit: 70 Sec  Memory Limit: 512 MBSubmit: 2168  Solved: 947[Submit][Status] ...

  6. 【BZOJ4012】[HNOI2015]开店 动态树分治+二分

    [BZOJ4012][HNOI2015]开店 Description 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点 ...

  7. BZOJ4012 [HNOI2015]开店

    Description 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的 想法当然非常好啦,但是她们也发现 ...

  8. bzoj 4012: [HNOI2015]开店

    Description 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的 想法当然非常好啦,但是她们也发现 ...

  9. bzoj 4012: [HNOI2015]开店 主席树

    Description 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的 想法当然非常好啦,但是她们也发现 ...

随机推荐

  1. Mapreduce shuffle和排序

    Mapreduce为了确保每个reducer的输入都按键排序.系统执行排序的过程-----将map的输出作为输入传给reducer 称为shuffle.学习shuffle是如何工作的有助于我们理解ma ...

  2. python 使用sk_learn 遇到 问题ValueError: Expected 2D array, got 1D array instead:

    这里我找到我的问题是: 使用的是一个新的scikit学习版本,它抛出了一个错误,因为在新版本中,所有东西都必须是一个二维矩阵,甚至是一个列或行. 它甚至说:用数组来重塑你的数据.如果您的数据有一个单独 ...

  3. 计算机信息类ComputerInfo

    using System; using System.Management; using System.Net; using System.Net.Sockets; using System.Text ...

  4. https配置指导

    为了使Apache支持https访问,系统需要安有apache.openssl.mod_ssl.so 证书申请 https://ninghao.net/blog/4449 安装证书时 安装编译open ...

  5. Oracle LSNRCTL------监听器的启动和关闭

    对于DBA来说,启动和关闭oracle监听器是很基础的任务,但是Linux系统管理员或者程序员有时也需要在开发数据库中做一些基本的DBA操作,因此了解一些基本的管理操作对他们来说很重要. 本文将讨论用 ...

  6. java代码,实现输入编号,输出对应水果的单价~~~~

    总结:总感觉有问题,因为输出我写的太不对劲了,直接把price的价格写了出来然输出显示…… package com.badu; import java.util.Scanner; //从键盘输入次数, ...

  7. 微服务监控之二:Metrics+influxdb+grafana构建监控平台

    系统开发到一定的阶段,线上的机器越来越多,就需要一些监控了,除了服务器的监控,业务方面也需要一些监控服务.Metrics作为一款监控指标的度量类库,提供了许多工具帮助开发者来完成自定义的监控工作. 使 ...

  8. 支付宝pc端支付接入PHP实现

    引入支付宝接口 放入一个插件库中,方便管理 创建支付类 1.发起支付 public function init() { $order_id = $_REQUEST['order_id']; $orde ...

  9. C# winform程序免安装.net framework在XP/win7/win10环境运行!(转)

    C# winform程序免安装.net framework在XP/win7/win10环境运行!   前文: 首先感谢群里的大神宇内流云 提供的anyexec for windows版本. 经过本人搭 ...

  10. ubuntu12 安装redis和phpRedisAdmin详细流程

    一.Ubuntu安装redis(redis默认端口6379) 方式一.直接下载源码,编译(redis可以编译源码之后直接运行,不需要安装) 1.1执行命令,从官网下载源码编译: $ wget http ...