一、题目

点此看题
题目描述
浩浩荡荡的cg大军发现了一座矿产资源极其丰富的城市,他们打算在这座城市实施新的采矿战略。这个城市可以看成一棵有n个节点的有根树,我们把每个节点用1到n的整数编号。为了方便起见,对于任何一个非根节点v,它任何一个祖先的编号都严格小于v。树上的每个节点表示一个矿点,每条边表示一条街道。作为cg大军的一个小队长,你拥有m个部下。你有一张二维的动态信息表,用Ti,j表示第i行第j列的数据。当你被允许开采某个区域时,你可以将你的部下分配至各个矿点。在第i个矿点安排j个人可以获得Ti,j单位的矿产。允许开采的区域是这样描述的:给你一对矿点(u,v),保证v是u的祖先(这里定义祖先包括u本身);u为你控制的区域,可以在以u为根的子树上任意分配部下;u到v的简单路径(不包括u但包括v,若u=v则包括u)为探险路径,在该路径上你可以选择至多一个矿点安排部下。你这次开采的收益为安排有部下的矿点的收益之和。
输入格式
输入的第一行包含5个正整数n、m、A、B、Q。n为矿点的个数,m为部下的数量。A、B、Q是与动态信息表有关的数据。第二行包含n-1个正整数,第i个数为Fi+1,表示节点i+1的父亲。接下来需要你用下文的方法依次生成n组数据,每组数据共m个。其中第i组的m个数据为信息表中第i行的m个数据。紧接着一行包含一个正整数C,表示事件的数量。最后给出C行,每行描述一个事件。每个事件会先给出一个0或1的整数。如果该数为0,则后面有一个正整数p,表示动态信息表有更新,你需要生成一组m个数据,来替换信息表中第p行的m个数据。如果该数为1,则后面有两个正整数u、v,表示出现了一个你可以开采的区域,你需要回答这次开采的收益。同一行的各个数之间均用一个空格隔开,没有多余的空格和换行。数据的生成方法如下:每次生成一组m个从小到大排列的数据,替换动态信息表的一行。其中,从小到大第j个数替换信息表中第j列的数。调用以下代码m次并排序得到一组数据。(注意可能会出现重复的数)函数GetInt A←((A xor B)+(B div X)+(B * X))and Y B←((A xor B)+(A div X)+(A * X))and Y 返回(A xor B)mod Q 其中A、B、Q均用32位有符号整数保存(C/C++的signed long int类型,pascal的longint类型),X=216(2的16次方),Y=231-1(2的31次方-1),xor为位异或运算,div为整除运算,and为位且运算,mod为取余运算。由于只保留了低31位,易得我们不用考虑数据的溢出问题。(注意每次A和B都会被改变)
输出格式
对于每个开采事件(开头为1的事件),输出一行一个整数,为每次的收益。
数据范围
1 ≤ n ≤ 20000 , 1 ≤ m ≤ 50 , 1 ≤ C ≤ 2000 1\leq n\leq 20000,1\leq m\le50,1\leq C\leq 2000 1≤n≤20000,1≤m≤50,1≤C≤2000

二、解法

输入有点复杂,但是题意很清楚,突破本题的关键是1<=m<=50,我们可以考虑跑 d p dp dp, f a u fa_u fau​到 v v v可以直接将每一位都取最大值, u u u的子树内可以用类似背包的方式暴力合并(设 f i f_i fi​有 i i i个人的最大收益),在把两个求出来的数组合并。

考虑优化,可以用树链剖分,维护区间的最大值和区间的合并结果,修改就是单点修改,为了方便写,我们可以直接重载+,*号,对于 f a u fa_u fau​到 v v v求链上最大值, u u u子树内求合并结果,再直接相乘,时间复杂度 O ( C ( log ⁡ 2 n × m + log ⁡ n × m 2 ) ) O(C(\log^2 n\times m+\log n\times m^2)) O(C(log2n×m+logn×m2))

#pragma GCC optimize(2)
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
using namespace std;
const int M = 20005;
const int N = 51;
int read()
{int x=0,flag=1;char c;while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();return x*flag;
}
int n,m,q,A,B,Q,X=1<<16,Y=~0U>>1,tot,siz[M],f[M],fa[M];
int Index,son[M],dep[M],num[M],top[M],st[M];
struct edge
{int v,next;edge(int V=0,int N=0) : v(V) , next(N) {}
}e[2*M];
struct node
{LL a[N];node() {memset(a,0,sizeof a);}void clear() {memset(a,0,sizeof a);}node operator + (const node &B) const{node r;for(int i=1;i<=m;i++)r.a[i]=max(a[i],B.a[i]);return r;}node operator * (const node &B) const{node r;for(int i=0;i<=m;i++)for(int j=0;j<=m-i;j++)r.a[i+j]=max(r.a[i+j],a[i]+B.a[j]);return r;}void print(){for(int i=1;i<=m;i++)printf("%lld ",a[i]);puts("");return ;}
}tmp,emp,a[M],t1[4*M],t2[4*M];
int getint()
{A=((A^B)+B/X+B*X)&Y;B=((A^B)+A/X+A*X)&Y;return (A^B)%Q;
}
void get_tmp()
{for(int i=1;i<=m;i++) tmp.a[i]=getint();sort(tmp.a+1,tmp.a+1+m);//tmp.print();
}
void dfs1(int u,int p)
{fa[u]=p;dep[u]=dep[p]+1;siz[u]=1;for(int i=f[u];i;i=e[i].next){int v=e[i].v;if(v==p) continue;dfs1(v,u);siz[u]+=siz[v];if(siz[v]>siz[son[u]])son[u]=v;}
}
void dfs2(int u,int tp)
{top[u]=tp;num[u]=++Index;st[Index]=u;if(son[u]) dfs2(son[u],tp);for(int i=f[u];i;i=e[i].next)if(e[i].v^son[u] && e[i].v^fa[u])dfs2(e[i].v,e[i].v);
}
void up(int i)
{t1[i]=t1[i<<1]*t1[i<<1|1];t2[i]=t2[i<<1]+t2[i<<1|1];
}
void build(int i,int l,int r)
{if(l==r){t1[i]=t2[i]=a[st[l]];return ;}int mid=(l+r)>>1;build(i<<1,l,mid);build(i<<1|1,mid+1,r);up(i);
}
void updata(int i,int l,int r,int id)
{if(l==r){t1[i]=t2[i]=tmp;return ;}int mid=(l+r)>>1;if(mid>=id)updata(i<<1,l,mid,id);elseupdata(i<<1|1,mid+1,r,id);up(i);
}
node query1(int i,int l,int r,int L,int R)
{if(l>R || L>r) return emp;if(L<=l && r<=R) return t1[i];int mid=(l+r)>>1;return query1(i<<1,l,mid,L,R)*query1(i<<1|1,mid+1,r,L,R);
}
node query2(int i,int l,int r,int L,int R)
{if(l>R || L>r) return emp;if(L<=l && r<=R) return t2[i];int mid=(l+r)>>1;return query2(i<<1,l,mid,L,R)+query2(i<<1|1,mid+1,r,L,R);
}
node ask(int u,int v)
{node ans;while(top[u]^top[v]){if(dep[top[u]]<=dep[top[v]]) swap(u,v);ans=ans+query2(1,1,n,num[top[u]],num[u]);u=fa[top[u]];}if(dep[u]<=dep[v]) swap(u,v);ans=ans+query2(1,1,n,num[v],num[u]);return ans;
}
signed main()
{n=read();m=read();A=read();B=read();Q=read();for(int u=2;u<=n;u++){int v=read();e[++tot]=edge(v,f[u]),f[u]=tot;e[++tot]=edge(u,f[v]),f[v]=tot;}for(int i=1;i<=n;i++)get_tmp(),a[i]=tmp;dfs1(1,0);dfs2(1,1);build(1,1,n);q=read();while(q--){int op=read(),x=read();if(op==0){get_tmp();updata(1,1,n,num[x]);}else{int y=read();node t=query1(1,1,n,num[x],num[x]+siz[x]-1);if(x!=y) t=t*ask(fa[x],y);printf("%lld\n",t.a[m]);}}
}

BZOJ 2164 采矿相关推荐

  1. BZOJ.1558.[JSOI2009]等差数列(线段树 差分)

    BZOJ 洛谷 首先可以把原序列\(A_i\)转化成差分序列\(B_i\)去做. 这样对于区间加一个等差数列\((l,r,a_0,d)\),就可以转化为\(B_{l-1}\)+=\(a_0\),\(B ...

  2. S-T平面图中利用最短路求最小割(BZOJ 1001)

    BZOJ 1001: [BeiJing2006]狼抓兔子 最小割 题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1001 现在小朋友们最喜欢 ...

  3. BZOJ 1124: [POI2008]枪战Maf(构造 + 贪心)

    题意 有 \(n\) 个人,每个人手里有一把手枪.一开始所有人都选定一个人瞄准(有可能瞄准自己).然后他们按某个顺序开枪,且任意时刻只有一个人开枪. 因此,对于不同的开枪顺序,最后死的人也不同. 问最 ...

  4. BZOJ 2957楼房重建

    传送门 线段树 //Twenty #include<cstdio> #include<cstdlib> #include<iostream> #include< ...

  5. BZOJ.5249.[九省联考2018]iiidx(贪心 线段树)

    BZOJ LOJ 洛谷 \(d_i\)不同就不用说了,建出树来\(DFS\)一遍. 对于\(d_i\)不同的情况: Solution 1: xxy tql! 考虑如何把这些数依次填到树里. 首先对于已 ...

  6. 洛谷P2380 狗哥采矿

    P2380 狗哥采矿 题目背景 又是一节平静的语文课 狗哥闲来无事,出来了这么一道题 题目描述 一个n*m的矩阵中,每个格子内有两种矿yeyenum和bloggium,并且知道它们在每个格子内的数量是 ...

  7. bzoj 4871: [Shoi2017]摧毁“树状图”

    4871: [Shoi2017]摧毁"树状图" Time Limit: 25 Sec  Memory Limit: 512 MB Submit: 53  Solved: 9 [Su ...

  8. BZOJ 1592. Making the Grade(思维,数据结构优化DP,以及三个拓展问题)[Usaco2008 Feb]【BZOJ计划】

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 BZOJ简单题合集x 目录 BZOJ 1592. Making the Grade 拓展问题一 拓展问 ...

  9. BZOJ 1590.Secret Message 秘密信息(Trie树) [Usaco2008 Dec]【BZOJ计划】

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 BZOJ简单题合集x Weblink https://hydro.ac/d/bzoj/p/1590 P ...

最新文章

  1. 跳车开发者Pokkst自述——从BTC到BCH
  2. php mysql事务
  3. UCINET 社会网络分析工具
  4. java list取值_Java集合详解
  5. c语言多进程架构改go语言,golang多进程并发
  6. 解剖 Nginx ·自动脚本篇(1)解析配置选项脚本 auto/options
  7. 分布式机器学习框架:MxNet
  8. python功能函数_Python-功能函数的使用
  9. 计算机管理员四级,计算机四级基本知识点
  10. BizTalkServer 如何发送 EDI 消息(3)
  11. myeclipse 报内存不足的解决方法
  12. Vue-购物车简单案例
  13. 目标检测数据集标注工具LabelImg从安装到使用详解
  14. MATLAB视频运动目标检测
  15. 如何从Win11系统安装回win10系统?
  16. 需求分析师如何做好非功能性需求
  17. dva开发框架简介和演示
  18. 录屏可以录声音吗?录制带声音的视频,这个方法轻松解决
  19. [计算几何]Last Stardust
  20. pythonmathcot函数_NumPy数学函数介绍和用法

热门文章

  1. 小米怎么就“不行”了呢?疫情之下谁顶不住
  2. 图书-管理:《80/20定律》
  3. java @literal_Java Literal.getText方法代碼示例
  4. 解决ElementUI导航栏中的vue-router在3.0版本以上重复点菜单报错问题
  5. MYSQL使用binlog日志恢复数据
  6. 做物联网卡代理需要什么技巧?有哪些注意事项要考虑?
  7. [SQL Server]TOP的用法
  8. Poco线程池使用实例
  9. 调用API让声卡发出声音
  10. matlab实验一 图像增强