HDU 6609 离散化+权值线段树
题意
有一个长度为\(n\)的数组W;
对于每一个\(i\)(\(1<=i<=n\)),你可以选择中任意一些元素W[k] (\(1<=k<i\)),将他们的值改变为0,使得\(\sum_{j=1}^{i-1}W[j] <= m\),
所以输出n个数字,代表对于每一个\(i\),要满足以上条件,至少改变多少个元素.
想法
做这个题的时候,我一直想着怎样贪心,然后一直想不出.
一般来说第一反应应该会是先改变大的元素,但是也可以去考虑保留小的元素.
可以权值线段树+离散化.
离散化之后,用一颗权值线段树维护在前\(i-1\)个元素中,每一种元素出现了多少次.
线段树上每个节点记录每个区间内的元素出现过多少次,和每个区间内所有元素的和.
对于每一个\(i\),我们在前\(i-1\)个元素里面找到尽量多的元素,使它们的和不大于\(m-W[i]\).
在查询的时候,
如果一个节点的和小于\(m-W[i]\),那么答案直接加上这个区间上的元素的个数,即这个区间的元素都保留.
否则如果左子树上的和大于\(m-W[i]\),那么就从左子树中找应该保留哪些数,
如果左子树上的和小于\(m-W[i]\),,那么就保留左子树上的所有元素并且在右子树中找还需要哪些元素,即在右子树中查询不大于\(m-W[i]-\sum左子树上的数\).
代码
#include<stdio.h>
#include<vector>
#include<algorithm>
typedef long long ll;
const int MAXN = 200100;
class Node{
public:
int l, r, num;//l,r是区间的范围,num是区间上的数的出现次数
ll val;//val是区间上的数的和
Node *lson, *rson;//左右子树
Node(int _l, int _r);
int mid();
int query(int k);
void update(int pos, int _val);
void clear();
};
Node::Node(int _l, int _r){//建线段树
l = _l, r = _r, val = 0, num = 0;
if(l != r){
lson = new Node(l, mid());
rson = new Node(mid()+1, r);
}
}
void Node::clear(){//删除线段树
if(l!=r){
lson->clear();
rson->clear();
delete lson;
delete rson;
}
}
int Node::mid(){//求l和r的平均值
return (l+r)>>1;
}
int Node::query(int _val){//查询,在不大于_val的情况下,应该保留哪些数字
if(val <= _val) return num;//保留整个区间,直接返回num
if(l == r) return (_val*num/val);//区间范围为1(即只有一个数)的时候,返回能保留多少个这个数字
if(lson->val>_val) return lson->query(_val);
else return lson->num+rson->query(_val-lson->val);//保留左子树上的所有数字,查询右子树
}
void Node::update(int pos, int _val){
if(l == r){
val+=_val,num++;
return;
}
if(pos<l || pos>r) return;
if(pos<=mid()) lson->update(pos, _val);
else rson->update(pos, _val);
num = lson->num+rson->num;
val = lson->val+rson->val;
}
int W[MAXN], uniqueW[MAXN];
int main(){
int t;
scanf("%d", &t);
while(t--){
int maxW, n, m;
Node *seqTree = 0;
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++i)
scanf("%d", W+i), uniqueW[i] = W[i];
std::sort(uniqueW+1, uniqueW+n+1);//离散化
maxW = std::unique(uniqueW+1, uniqueW+n+1)-(uniqueW+1);
seqTree = new Node(1, maxW);//建立一颗空的线段树,一开始没有任何的元素
for(int i = 1; i <= n ; ++i){
int pos = std::lower_bound(uniqueW+1, uniqueW+maxW+1, W[i])-(uniqueW);//找W[i]离散化之后的位置
printf("%d ", i-seqTree->query(m-W[i])-1);//query返回的是保留的数,i-query-1就是应该改变的数
seqTree->update(pos, uniqueW[pos]);//把W[i]插入线段树
}
seqTree->clear();//删除一下,以免mle
printf("\n");
}
}
HDU 6609 离散化+权值线段树的更多相关文章
- R - Weak Pair HDU - 5877 离散化+权值线段树+dfs序 区间种类数
R - Weak Pair HDU - 5877 离散化+权值线段树 这个题目的初步想法,首先用dfs序建一颗树,然后判断对于每一个节点进行遍历,判断他的子节点和他相乘是不是小于等于k, 这么暴力的算 ...
- BZOJ_3224 Tyvj 1728 普通平衡树 【离散化+权值线段树】
一 题面 Tyvj 1728 普通平衡树 二 分析 比较明显是可以用平衡二叉搜索树(splay)做的. 用权值线段树做,前提就是要先离散化,因为权值线段树维护的值域信息. 板子. 三 AC代码 #in ...
- hdu 6703 array(权值线段树)
Problem Description You are given an array a1,a2,...,an(∀i∈[1,n],1≤ai≤n). Initially, each element of ...
- 2019年CCPC网络赛 HDU 6703 array【权值线段树】
题目大意:给出一个n个元素的数组A,A中所有元素都是不重复的[1,n].有两种操作:1.将pos位置的元素+1e72.查询不属于[1,r]中的最小的>=k的值.强制在线. 题解因为数组中的值唯一 ...
- bzoj1588: [HNOI2002]营业额统计(权值线段树)
1588: [HNOI2002]营业额统计 Time Limit: 5 Sec Memory Limit: 162 MBSubmit: 16863 Solved: 6789[Submit][Sta ...
- 线段树(单标记+离散化+扫描线+双标记)+zkw线段树+权值线段树+主席树及一些例题
“队列进出图上的方向 线段树区间修改求出总量 可持久留下的迹象 我们 俯身欣赏” ----<膜你抄> 线段树很早就会写了,但一直没有总结,所以偶尔重写又会懵逼,所以还是要总结一下. ...
- HDU 6464 免费送气球 【权值线段树】(广东工业大学第十四届程序设计竞赛)
传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6464 免费送气球 Time Limit: 2000/1000 MS (Java/Others) M ...
- HDU 6464 权值线段树 && HDU 6468 思维题
免费送气球 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submi ...
- 区间第k大问题 权值线段树 hdu 5249
先说下权值线段树的概念吧 权值平均树 就是指区间维护值为这个区间内点出现次数和的线段树 用这个加权线段树 解决第k大问题就很方便了 int query(int l,int r,int rt,int k ...
随机推荐
- 【高并发】高并发环境下构建缓存服务需要注意哪些问题?我和阿里P9聊了很久!
写在前面 周末,跟阿里的一个朋友(去年晋升为P9了)聊了很久,聊的内容几乎全是技术,当然了,两个技术男聊得最多的话题当然就是技术了.从基础到架构,从算法到AI,无所不谈.中间又穿插着不少天马行空的想象 ...
- 手牵手,从零学习Vue源码 系列二(变化侦测篇)
系列文章: 手牵手,从零学习Vue源码 系列一(前言-目录篇) 手牵手,从零学习Vue源码 系列二(变化侦测篇) 陆续更新中... 预计八月中旬更新完毕. 1 概述 Vue最大的特点之一就是数据驱动视 ...
- c++ string类型举例(递归预习的边界)
#include <iostream> #include <string> using namespace std; int main ( ) { string str; // ...
- Servlet学习之Tomcat控制台中文乱码问题
Tomcat控制台中文乱码问题 在更新了IDEA2020.1版本后,可以安装官方的简体中文插件,方便我们日常使用,但是更新后再运行Tomcat时,控制台的输出日志出现中文乱码问题,接下来告诉大家如何修 ...
- CF R631 div2 1330 E Drazil Likes Heap
LINK:Drazil Likes Heap 那天打CF的时候 开场A读不懂题 B码了30min才过(当时我怀疑B我写的过于繁琐了. C比B简单多了 随便yy了一个构造发现是对的.D也超级简单 dp了 ...
- luogu4443 coci 2017 Dajave
题目 给出一个长度为2^M的排列,元素分别是0, 1, 2, ... , 2^M -1. 选择其中某个非空连续子序列,然后允许交换这个排列中某两个不同的数,然后使得这个连续子序列的所有数的按位异或(b ...
- 如何在Spring异步调用中传递上下文
以下文章来源于aoho求索 ,作者aoho 1. 什么是异步调用? 异步调用是相对于同步调用而言的,同步调用是指程序按预定顺序一步步执行,每一步必须等到上一步执行完后才能执行,异步调用则无需等待上一步 ...
- jmeter分布式踩得坑汇总
一.普通的配置文件基本都能网上搜索资料,这里就简单记录: a.jmeter.properties几处修改:1.remote_hosts=master压力机Ip;2.server_port,开启服务器端 ...
- 【BZOJ2821】作诗 题解(分块+前缀和)
前言:世间还有这么卡常的题…… ------------------ 题目链接 题目大意:给定长度为$n$的序列${a_i}$.有$m$次询问,问$[l,r]$内出现正偶数次的数字有多少个. 这题跟蒲 ...
- 为什么阿里规定需要在事务注解@Transactional中指定rollbackFor?
作者:Mint6 来源:http://39sd.cn/53D5D Java阿里巴巴规范提示:方法[edit]需要在Transactional注解指定rollbackFor或者在方法中显示的rollba ...