BZOJ2809&&LG1552 APIO2012派遣(线段树合并)
BZOJ2809&&LG1552 APIO2012派遣(线段树合并)
题面
自己找去
HINT
简化一题面就是让你从每个点的子树中以\(<=m\)的代价选取尽可能多的点,然后乘上子树根的一个属性值,每个点做一遍取个\(max\)。看大家都是什么可并堆、dfs序+主席树,我的做法是对于每个节点开一颗权值线段树,每个节点维护\(size\)和\(tot\),然后修改和线段树合并都是常规写法。
着重讲一下查询
这样的写法之后就是要实现查询用m的代价可以最多选择多少个点
inline int query(int p,long long rk,int l,int r){
if(!p) return 0;//如果进入了空节点,就肯定没有可选的,返回0
if(l==r){
int x=st[p].tot/st[p].size;return min((long long)rk/x,(long long)st[p].size);
//这里是重点,查询到该点的时候我还有rk的剩余,已经到叶子节点了,这个时候我们就要计算一下自己最多可以选多少个,如果能都选就都选,如果不能多选就尽量选满
}
long long now=st[ls(p)].tot;int mid=(l+r)>>1;
if(rk<=now) return query(ls(p),rk,l,mid);
else return st[ls(p)].size+query(rs(p),rk-now,mid+1,r);
}
其他的看代码吧
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define ls(x) st[x].ch[0]
#define rs(x) st[x].ch[1]
using namespace std;
inline int read(){
int w=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
w=(w<<3)+(w<<1)+ch-48;
ch=getchar();
}
return w*f;
}
int n,m,cur,root[100010],a[100010],b[100010],val[100010],now[100010];
long long l[100010],ans[100010];
bool debug;
struct CHAIRMANTREE{
struct Node{
int size,ch[2];long long tot;
}st[6000010];
int tot;
inline void pushup(int x){
st[x].size=st[ls(x)].size+st[rs(x)].size;
st[x].tot=st[ls(x)].tot+st[rs(x)].tot;return;
}
inline int change(int p,int l,int r,int pos,int val){
if(!p)p=++tot;
if(l==r){
st[p].size+=1;st[p].tot+=val;return p;
}
int mid=(l+r)>>1;
if(pos<=mid) ls(p)=change(ls(p),l,mid,pos,val);
else rs(p)=change(rs(p),mid+1,r,pos,val);
pushup(p);return p;
}
inline int merge(int x,int y,int l,int r){
if(!x||!y) return x|y;
int p=++tot;
if(l==r){
st[p].size=st[x].size+st[y].size;
st[p].tot=st[x].tot+st[y].tot;return p;
}
int mid=(l+r)>>1;
ls(p)=merge(ls(x),ls(y),l,mid);
rs(p)=merge(rs(x),rs(y),mid+1,r);
pushup(p);return p;
}
inline int query(int p,long long rk,int l,int r){
if(!p) return 0;
if(l==r){
int x=st[p].tot/st[p].size;return min((long long)rk/x,(long long)st[p].size);
}
long long now=st[ls(p)].tot;int mid=(l+r)>>1;
if(rk<=now) return query(ls(p),rk,l,mid);
else return st[ls(p)].size+query(rs(p),rk-now,mid+1,r);
}
}TREE;
int cnt,head[100010];
struct Edge{
int from,to,next;
}edge[200010];
inline void addedge(int u,int v){
cnt++;
edge[cnt].from=u;
edge[cnt].to=v;
edge[cnt].next=head[u];
head[u]=cnt;
}
map<int,int> mapp;
inline void prework(){
sort(a+1,a+n+1);
for(int i=1;i<=n;i++){
if(!mapp[a[i]]){
cur++;mapp[a[i]]=cur;b[cur]=a[i];
}
}
for(int i=1;i<=n;i++){
val[i]=mapp[val[i]];
}
}
inline void dfs(int u){
root[u]=TREE.change(root[u],1,cur,val[u],now[u]);
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].to;dfs(v);
root[u]=TREE.merge(root[u],root[v],1,cur);
}
if(debug)cout<<"test"<<u<<endl;
ans[u]=(long long)TREE.query(root[u],m,1,cur);
if(debug){
cout<<u<<" "<<ans[u]<<endl;
}
}
signed main(){
n=read();m=read();
for(int i=1;i<=n;i++){
int x=read();addedge(x,i);
now[i]=a[i]=val[i]=read();l[i]=read();
}
prework();
//debug=true;
dfs(1);
long long Ans=-1;
for(int i=1;i<=n;i++){
//cout<<l[i]<<" "<<ans[i]<<endl;
Ans=max(Ans,l[i]*ans[i]);
}
cout<<Ans<<endl;
return 0;
}
BZOJ2809&&LG1552 APIO2012派遣(线段树合并)的更多相关文章
- [XJOI NOI2015模拟题13] C 白黑树 【线段树合并】
题目链接:XJOI - NOI2015-13 - C 题目分析 使用神奇的线段树合并在 O(nlogn) 的时间复杂度内解决这道题目. 对树上的每个点都建立一棵线段树,key是时间(即第几次操作),动 ...
- [BZOJ 2212] [Poi2011] Tree Rotations 【线段树合并】
题目链接:BZOJ - 2212 题目分析 子树 x 内的逆序对个数为 :x 左子树内的逆序对个数 + x 右子树内的逆序对个数 + 跨越 x 左子树与右子树的逆序对. 左右子树内部的逆序对与是否交换 ...
- BZOJ 3307: 雨天的尾巴( LCA + 线段树合并 )
路径(x, y) +z : u处+z, v处+z, lca(u,v)处-z, fa(lca)处-z, 然后dfs一遍, 用线段树合并. O(M log M + M log N). 复杂度看起来不高, ...
- BZOJ2733 [HNOI2012]永无乡 【线段树合并】
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...
- bzoj 2243 [SDOI2011]染色(树链剖分+线段树合并)
[bzoj2243][SDOI2011]染色 2017年10月20日 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询 ...
- bzoj3702二叉树 线段树合并
3702: 二叉树 Time Limit: 15 Sec Memory Limit: 256 MBSubmit: 600 Solved: 272[Submit][Status][Discuss] ...
- BZOJ_2212_[Poi2011]Tree Rotations_线段树合并
BZOJ_2212_[Poi2011]Tree Rotations_线段树合并 Description Byteasar the gardener is growing a rare tree cal ...
- B20J_2733_[HNOI2012]永无乡_权值线段树合并
B20J_2733_[HNOI2012]永无乡_权值线段树合并 Description:n座岛,编号从1到n,每座岛都有自己的独一无二的重要度,按照重要度可以将这n座岛排名,名次用1到 n来表示.某些 ...
- BZOJ_3307_雨天的尾巴_线段树合并+树上差分
BZOJ_3307_雨天的尾巴_线段树合并 Description N个点,形成一个树状结构.有M次发放,每次选择两个点x,y 对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成 所有发放后 ...
随机推荐
- golang的timer一些坑
本文代码部分基于dive-to-gosync-workshop的代码 Golang 的NewTimer方法调用后,生成的timer会放入最小堆,一个后台goroutine会扫描这个堆,将到时的time ...
- JAVA中voltatile关键字的使用
1.首先要明白一个概念 JAVA中主内存和线程工作内存的概念. 如果有一个static的变量,值会存储在主内存.如果多个线程访问这个变量,每个线程都会将变量的值拷贝到自己的工作内存,之后的操作就是针对 ...
- echarts 的 formatter用法
前言:formatter格式化方法.使用formatter调用自定义的数据,把内容通过处理让变成我们想要的样子. 比如,echarts数据显示是这样的(bug:部分内容被隐藏掉了,显示太长,不美观) ...
- get、post请求参数乱码解决方法(qq:1324981084)
java高级架构师全套vip教学视频,需要的加我qq1324981084 在实际的项目中我们会遇见中文乱码的问题,这个问题是很恶心的事,所以我在这里提供了一些解决中文乱码的方法,希望能给大家一些帮助. ...
- codewars--js--Two Joggers--求最小公倍数、最大公约数
问题描述: Two Joggers Description Bob and Charles are meeting for their weekly jogging tour. They both s ...
- Vue中的递归组件
递归函数我们都再熟悉不过了,也就是函数自己调用自己.递归组件也是类似的,在组件的template内部使用组件自身.那递归组件有什么使用场景呢? 我们都知道树这个数据结构就是一种递归的结构,因此我们可以 ...
- Shiro知识初探(更新中)
Shiro 是当下常见的安全框架,主要用于用户验证和授权操作. RBAC 是当下权限系统的设计基础,同时有两种解释:一: Role-Based Access Control,基于角色的访问控制即,你要 ...
- 如何避免FOUC,是如何产生的
FOUC(Flash Of Unstyled Content)即浏览器样式闪烁或者叫做无样式内存闪烁(用户定义样式表加载之前浏览器使用默认样式显示文档,用户样式加载渲染之后再从新显示文档,造成页面闪烁 ...
- OpenResty + ngx_lua_waf使用
本篇介绍在CentOS7.6上安装.测试使用ngx_lua_waf + openresty. Preface # yum install epel-release -y # yum group ins ...
- mongo curd
常用命令 未完待续...