hdu4614Vases and Flowers 线段树

//给一个数组,两个操作

//1 A F 以A为起点的F个空闲空间插花,输出起点和终点

//2 L R 将[L , R]的所有的有花的花拔除,问清除了几朵花

//用线段树维护剩余空间的个数

//然后再在查询时找出空间

#include<cstdio>

#include<cstring>

#include<iostream>

using namespace std ;

const int maxn = 50010 ;

#define left v<<1

#define right v<<1|1

struct node

{

int l  ,r ,value ;

int lazy ;

}tree[maxn<<2] ;

void build(int l , int r , int v)

{

tree[v].l = l ;

tree[v].r = r ;

tree[v].value = (r - l + 1) ;

tree[v].lazy = -1 ;

if(l == r) return  ;

int mid = (l + r) >> 1 ;

build(l , mid , left) ;

build(mid + 1 , r , right) ;

}

void push_down(int v)

{

if(tree[v].lazy != -1)

{

tree[left].lazy = tree[right].lazy = tree[v].lazy ;

tree[left].value = (tree[left].r - tree[left].l + 1)*tree[v].lazy ;

tree[right].value = (tree[right].r - tree[right].l + 1)*tree[v].lazy ;

tree[v].lazy = -1 ;

}

}

int getsum(int l , int r , int v)

{

if(l <= tree[v].l && tree[v].r <= r)

return tree[v].value ;

push_down(v) ;

int mid = (tree[v].l + tree[v].r) >> 1 ;

if(r <= mid)return getsum(l , r , left) ;

else if(l > mid)return getsum(l , r , right) ;

else return getsum(l , mid , left) + getsum(mid+1 , r , right) ;

}

int  update(int l , int r , int op , int v)

{

if(l <= tree[v].l && tree[v].r <= r)

{

int ans = (tree[v].r - tree[v].l + 1 - tree[v].value) ;

tree[v].value = (tree[v].r - tree[v].l + 1)*op ;

tree[v].lazy = op ;

return ans;

}

push_down(v) ;

int mid = (tree[v].l + tree[v].r) >> 1 ;

int ans ;

if(l > mid)ans =  update(l , r , op , right) ;

else if(r <= mid)ans = update(l , r , op , left) ;

else ans = (update(l , mid , op , left) + update(mid + 1 , r , op , right)) ;

tree[v].value = (tree[left].value + tree[right].value) ;

return ans ;

}

int query(int pos , int &sum , int v)

{

if(tree[v].l == tree[v].r)

{

if(tree[v].value == 1)sum--;

return tree[v].l ;

}

int mid = (tree[v].l + tree[v].r) >> 1 ;

push_down(v) ;

if(pos <= mid)

{

int sum_1 = 0 ;

if(pos > tree[v].l)

sum_1 = getsum(tree[v].l , pos - 1 , left) ;

int sum_2 = tree[left].value ;

if(sum <= (sum_2 - sum_1))

return query(pos , sum , left) ;

sum -= (sum_2 - sum_1) ;

return query(mid + 1 , sum , right) ;

}

else if(pos > mid)

return query(pos , sum , right) ;

}

int main()

{

//freopen("in.txt" ,"r" ,stdin) ;

int T ;

scanf("%d" , &T) ;

while(T--)

{

int  n , m  ;

scanf("%d%d" , &n , &m) ;

build(1 , n , 1) ;

int K , A , F ;

while(m--)

{

scanf("%d%d%d" ,&K , &A , &F ) ;

if(K == 1)

{

int sum = F ;

int temp ;int ans_l , ans_r ;

int sum_r = getsum(A+1, n , 1) ;

if(sum_r == 0)puts("Can not put any one.");

else

{

sum = (sum_r > F) ? F : sum_r ;

ans_r = query(A+1 ,  sum , 1) ;

sum = 1;

ans_l = query(A+1 , sum, 1) ;

printf("%d %d\n", ans_l - 1 , ans_r - 1) ;

update(ans_l , ans_r , 0 , 1) ;

}

}

if(K == 2)

printf("%d\n" , update(A+1 , F+1 , 1 , 1)) ;

}

puts("") ;

}

return 0 ;

}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-04 13:22:11

hdu4614Vases and Flowers 线段树的相关文章

HDU 4614 Vases and Flowers 线段树+二分

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4614 题意:N个花瓶,两种操作. 操作1:从第a个花瓶开始放花,放最多f个,如果花瓶已经有花就跳过,直到放完,或者无更多花瓶,要求输出这次放花的第一个位置和最后一个位置,如果没放就输出Cannot... 操作2:将花瓶a到b区间内的花都扔了,然后输出扔掉的花的数目. 解题思路:花瓶有花为0,无花为1,那么实际上这是一个区间更新以及求和,求左右端点的问题.线段树节点维护一个 sum--区间和,lid-

hdoj 4325 Flowers 线段树+离散化

hdoj 4325 Flowers 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4325 思路: 直接线段树,按照花的开放区间的大小建树,要注意虽然花的周期数据可能会达到1e9,这样的话线段树开四倍时不可能的.但是我们可以看到一共可能的数据时N行,那么每行两个数,再开4倍的区间.计算下来,在离散化的帮助下,我们只需要开8*N被的线段树即可. 另外询问的数据也需要放入离散化的范围,如果不这样做,有可能在询问时使用lower_bound函数会导致数

HDU4614Vases and Flowers 二分+线段树;

参考:https://blog.csdn.net/ophunter_lcm/article/details/9879495 题意: 有n个花瓶,有两种操作,1.从a开始放b朵花,有花的花瓶跳过,2.把a到b间的花全部拿下来. 思路: 线段树+二分 利用二分确定区间,这样就可以是线段树实现更简单的问题: 1)对区间进行全部设置为1的操作 2)对区间进行全部清零的操作 #include <iostream> #include <cstdio> #include <algorith

HDU 4614 Vases and Flowers(线段树区间更新+二分)

Problem Description Alice is so popular that she can receive many flowers everyday. She has N vases numbered from 0 to N-1. When she receive some flowers, she will try to put them in the vases, one flower in one vase. She randomly choose the vase A a

【HDU 4614】Vases and Flowers(线段树区间更新懒惰标记)

题目0到n-1的花瓶,操作1在下标a开始插b朵花,输出始末下标.操作2清空[a,b]的花瓶,求清除的花的数量.线段树懒惰标记来更新区间.操作1,先查询0到a-1有num个空瓶子,然后用线段树的性质,或者二分找出第num+1个空瓶子的下标,和第num+b个空瓶子的下标.再区间更新为满.操作2,也相当于区间更新为空. #include<cstdio> #include<cstring> #include<algorithm> #define N 50001 using na

HDU-4614 Vases and Flowers (线段树区间更新)

题目大意:有n个花瓶,每个花瓶中只能放一朵花.两种操作,一种是从A开始放F朵花,如果有的花瓶中已经有花则跳过这个花瓶,往下一个花瓶放:第二种是将区间[A,B]之间花瓶中的花清空.如果是第一种操作,输出这次放的花的左右端点:如果是第二种操作,输出这次总共清理出了多少支花. 题目分析:建立线段树,节点维护在相应的区间中,没有放入花的花瓶数目.有三种操作:一.查询某个区间中第k个没有插入花的花瓶位置:二.更新区间,使区间全部插入花:三.更新区间,使区间中的花瓶全部清空: 代码如下: # include

离散化+线段树/二分查找/尺取法 HDOJ 4325 Flowers

题目传送门 题意:给出一些花开花落的时间,问某个时间花开的有几朵 分析:这题有好几种做法,正解应该是离散化坐标后用线段树成端更新和单点询问.还有排序后二分查找询问点之前总花开数和总花凋谢数,作差是当前花开的数量,放张图易理解: 还有一种做法用尺取法的思想,对暴力方法优化,对询问点排序后再扫描一遍,花开+1,花谢-1.详细看代码. 收获:一题收获很多:1. 降低复杂度可以用二分 2. 线段计数问题可以在端点标记1和-1 3. 离散化+线段树 终于会了:) (听说数据很水?) 代码1:离散化+线段树

Vases and Flowers (二分 + 线段树)

题目链接:https://vjudge.net/contest/332656#problem/H 题意: n个花瓶,m个操作,花瓶里面有的有花,有的是空的. 1 x y 表示从第x个位置开始查y多花,若一朵花也插不上输出"Can not put any one.",反之输出插花的左位置和右位置. 2 操作是清除区间[a,b]的花.并输出清除了多少花. 思路:线段树维护区间,然后每次二分查找满足要求的第一个位置. 1 #include <math.h> 2 #include

【POJ 2750】 Potted Flower(线段树套dp)

[POJ 2750] Potted Flower(线段树套dp) Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4566   Accepted: 1739 Description The little cat takes over the management of a new park. There is a large circular statue in the center of the park, surrou