当前位置: 首页 > news >正文

Bzoj2164 采矿(线段树+树链剖分)

题面

Bzoj

题解

对于每个节点,我们可以用树链剖分和线段树维护以下信息:

  • 单独在某个点分配\(i\)个人的最大收益(可以\(O(m)\)计算)
  • 分配\(i\)的最大收益(可以\(O(m^2)\)计算)
#include <cstdio>
#include <cstring>
#include <algorithm>
using std::min; using std::max;
using std::sort; using std::swap;
typedef long long ll;

template<typename T>
void read(T &x) {
    int flag = 1; x = 0; char ch = getchar();
    while(ch < '0' || ch > '9') { if(ch == '-') flag = -flag; ch = getchar(); }
    while(ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); x *= flag;
}

const int N = 20010, M = 51, T = 65600;
int n, m, q, X = 1 << 16, Y = ~0U >> 1, A, B, Q, op, x, y;
int fa[N], son[N], siz[N], top[N], dfn[N], dep[N], val[N], tim;
int cnt, from[N], to[N], nxt[N];
inline void addEdge(int u, int v) {
    to[++cnt] = v, nxt[cnt] = from[u], from[u] = cnt;
}
struct P {
    ll v[M];
    P() { for(int i = 0; i < M; ++i) v[i] = 0; }
    P operator + (P b) {
        P c;
        for(int i = 0; i < M; ++i) c.v[i] = max(v[i], b.v[i]);
        return c;
    }
    P operator * (P b) {
        P c;
        for(int i = 0; i < M; ++i)
            for(int j = 0; j < M - i; ++j)
                c.v[i + j] = max(c.v[i + j], v[i] + b.v[j]);
        return c;
    }
}tmp, a[N], v0[T], v1[T], s0, s1;

//读入数据
inline int getint() {
    A = ((A ^ B) + B / X + B * X) & Y;
    B = ((A ^ B) + A / X + A * X) & Y;
    return (A ^ B) % Q;
}
inline void gettmp() {
    for(int i = 1; i <= m; ++i) tmp.v[i] = getint();
    sort(&tmp.v[1], &tmp.v[m + 1]);
}

//线段树
inline void pushup(int o, int lc, int rc) { v0[o] = v0[lc] + v0[rc], v1[o] = v1[lc] * v1[rc]; }
void build(int o = 1, int l = 1, int r = n) {
    if(l == r) { v0[o] = v1[o] = a[val[l]]; return ; }
    int mid = (l + r) >> 1, lc = o << 1, rc = lc | 1;
    build(lc, l, mid), build(rc, mid + 1, r), pushup(o, lc, rc);
}
void modify(int k, int o = 1, int l = 1, int r = n) {
    if(l == r) { v0[o] = v1[o] = tmp; return ; }
    int mid = (l + r) >> 1, lc = o << 1, rc = lc | 1;
    if(k <= mid) modify(k, lc, l, mid);
    else modify(k, rc, mid + 1, r);
    pushup(o, lc, rc);
}
void query0(int ql, int qr, int o = 1, int l = 1, int r = n) {
    if(l >= ql && r <= qr) { s0 = s0 + v0[o]; return ; }
    int mid = (l + r) >> 1, lc = o << 1, rc = lc | 1;
    if(ql <= mid) query0(ql, qr, lc, l, mid);
    if(qr > mid) query0(ql, qr, rc, mid + 1, r);
}
void query1(int ql, int qr, int o = 1, int l = 1, int r = n) {
    if(l >= ql && r <= qr) { s1 = s1 * v1[o]; return ; }
    int mid = (l + r) >> 1, lc = o << 1, rc = lc | 1;
    if(ql <= mid) query1(ql, qr, lc, l, mid);
    if(qr > mid) query1(ql, qr, rc, mid + 1, r);
}

//树链剖分
void dfs(int u) {
    siz[u] = 1, dep[u] = dep[fa[u]] + 1;
    for(int i = from[u]; i; i = nxt[i]) {
        int v = to[i]; dfs(v), siz[u] += siz[v];
        if(siz[v] > siz[son[u]]) son[u] = v;
    }
}
void dfs(int u, int t) {
    dfn[u] = ++tim, val[tim] = u, top[u] = t;
    if(!son[u]) return ; dfs(son[u], t);
    for(int i = from[u]; i; i = nxt[i])
        if(to[i] != son[u]) dfs(to[i], to[i]);
}
inline void Path(int x, int y) { //dep[y] 始终小于等于 dep[x]
    if(x == y) return ;
    x = fa[x]; int fx = top[x];
    while(fx != top[y]) query0(dfn[fx], dfn[x]), x = fa[fx], fx = top[x];
    query0(dfn[y], dfn[x]);
}

int main () {
#ifdef OFFLINE_JUDGE
    freopen("233.in", "r", stdin);
    freopen("233.out", "w", stdout);
#endif
    read(n), read(m), read(A), read(B), read(Q);
    for(int i = 2; i <= n; ++i)
        read(fa[i]), addEdge(fa[i], i);
    for(int i = 1; i <= n; ++i) gettmp(), a[i] = tmp;
    dfs(1), dfs(1, 1), build(), read(q);
    while(q--) {
        read(op), read(x);
        if(!op) gettmp(), modify(dfn[x]);
        else {
            read(y);
            s0 = s1 = P();
            Path(x, y), query1(dfn[x], dfn[x] + siz[x] - 1);
            s0 = s0 * s1;
            printf("%lld\n", s0.v[m]);
        }
    }
    return 0;
}

转载于:https://www.cnblogs.com/water-mi/p/10350601.html

相关文章:

  • 个位数统计
  • CF528D Fuzzy Search (生成函数+FFT)
  • c++随机数引擎
  • 《学习之道》第六章番茄工作法
  • 加密_滴答~滴
  • Ext中 grid 设置行样式
  • 技术研究 | 我所了解的物联网设备渗透手段(硬件篇)
  • Exif xss
  • C语言复习1_变量与数据类型
  • linux操作文本三个命令awk、grep、sed
  • 【c#】RabbitMQ学习文档(三)Publish/Subscribe(发布/订阅)
  • 食用指南
  • ffmpeg 推送、保存rtmp 流命令
  • 记账软件——第三天
  • 通过域对象获取当前项目的文件路径
  • [笔记] php常见简单功能及函数
  • 【108天】Java——《Head First Java》笔记(第1-4章)
  • Apache Zeppelin在Apache Trafodion上的可视化
  • ES6之路之模块详解
  • IDEA常用插件整理
  • iOS | NSProxy
  • Javascript弹出层-初探
  • Java-详解HashMap
  • Less 日常用法
  • RxJS: 简单入门
  • Spring Boot MyBatis配置多种数据库
  • Traffic-Sign Detection and Classification in the Wild 论文笔记
  • 前端性能优化--懒加载和预加载
  • 如何将自己的网站分享到QQ空间,微信,微博等等
  • 深度学习入门:10门免费线上课程推荐
  • 通过几道题目学习二叉搜索树
  • 白色的风信子
  • postgresql行列转换函数
  • 如何正确理解,内页权重高于首页?
  • ​Spring Boot 分片上传文件
  • ​一帧图像的Android之旅 :应用的首个绘制请求
  • #1015 : KMP算法
  • #HarmonyOS:基础语法
  • $ is not function   和JQUERY 命名 冲突的解说 Jquer问题 (
  • (LeetCode) T14. Longest Common Prefix
  • (NO.00004)iOS实现打砖块游戏(十二):伸缩自如,我是如意金箍棒(上)!
  • (分布式缓存)Redis哨兵
  • (附源码)基于SSM多源异构数据关联技术构建智能校园-计算机毕设 64366
  • (四)c52学习之旅-流水LED灯
  • (幽默漫画)有个程序员老公,是怎样的体验?
  • (转)Linux下编译安装log4cxx
  • **PHP二维数组遍历时同时赋值
  • .360、.halo勒索病毒的最新威胁:如何恢复您的数据?
  • .NET MVC、 WebAPI、 WebService【ws】、NVVM、WCF、Remoting
  • .NET/C# 异常处理:写一个空的 try 块代码,而把重要代码写到 finally 中(Constrained Execution Regions)
  • .net遍历html中全部的中文,ASP.NET中遍历页面的所有button控件
  • @RequestBody详解:用于获取请求体中的Json格式参数
  • [20171106]配置客户端连接注意.txt
  • [AIGC 大数据基础]hive浅谈
  • [BT]小迪安全2023学习笔记(第15天:PHP开发-登录验证)