hdu 4614 Vases and Flowers(线段树)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4614
题意:
给你N个花瓶,编号是0 到 N - 1 ,初始状态花瓶是空的,每个花瓶最多插一朵花。
然后有2个操作。
1)a b 往在a位置后面(包括a)插b朵花,输出插入的首位置和末位置。
2)a b 输出区间[a , b ]范围内的花的数量,然后全部清空。
操作看起来挺简单的但写起来还是有点复杂的
首先建树的时候可以设置变量first与ends分别表示一个区间最先出现的0和最后出现的0,sum=0
表示没放东西,sum=1表示放了。我们可以用二分来查找插完b朵花后的结尾区间。然后在寻找这个
区间的first与ends值之后就简单了。
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
using namespace std;
const int M = 5e4 + 10;
struct TnT {
int l , r , num , add , first , ends;
}T[M << 2];
int n , m;
void build(int l , int r , int p) {
int mid = (l + r) >> 1;
T[p].l = l , T[p].r = r , T[p].add = T[p].num = 0 , T[p].first = l , T[p].ends = r;
if(l == r) {
return ;
}
build(l , mid , p << 1);
build(mid + 1 , r , (p << 1) | 1);
}
void pushup(int p) {
T[p].num = T[p << 1].num + T[(p << 1) | 1].num;
if(T[p << 1].first == -1) {
T[p].first = T[(p << 1) | 1].first;
}
else if(T[(p << 1) | 1].first == -1) {
T[p].first = T[p << 1].first;
}
else {
T[p].first = min(T[(p << 1) | 1].first , T[p << 1].first);
}
if(T[(p << 1) | 1].ends == -1) {
T[p].ends = T[(p << 1) | 1].ends;
}
else if(T[(p << 1) | 1].ends == -1) {
T[p].ends = T[p << 1].ends;
}
else {
T[p].ends = max(T[(p << 1) | 1].ends , T[p << 1].ends);
}
}
void pushdown(int p) {
if(T[p].add == 1) {
T[p << 1].num = T[p << 1].r - T[p << 1].l + 1;
T[p << 1].first = -1;
T[p << 1].ends = -1;
T[(p << 1) | 1].num = T[(p << 1) | 1].r - T[(p << 1) | 1].l + 1;
T[(p << 1) | 1].first = -1;
T[(p << 1) | 1].ends = -1;
T[p << 1].add = T[p].add;
T[(p << 1) | 1].add = T[p].add;
}
if(T[p].add == -1) {
T[p << 1].first = T[p << 1].l;
T[p << 1].ends = T[p << 1].r;
T[p << 1].num = 0;
T[(p << 1) | 1].num = 0;
T[p << 1].add = T[p].add;
T[(p << 1) | 1].first = T[(p << 1) | 1].l;
T[(p << 1) | 1].ends = T[(p << 1) | 1].r;
T[(p << 1) | 1].add = T[p].add;
}
T[p].add = 0;
}
int query(int l , int r , int p) {
int mid = (T[p].l + T[p].r) >> 1;
if(T[p].l == l && T[p].r == r) {
return T[p].num;
}
pushdown(p);
if(mid >= r) {
return query(l , r , p << 1);
}
else if(mid < l) {
return query(l , r , (p << 1) | 1);
}
else {
return query(l , mid , p << 1) + query(mid + 1 , r , (p << 1) | 1);
}
}
int queryfr(int l , int r , int p) {
int mid = (T[p].l + T[p].r) >> 1;
if(T[p].l == l && T[p].r == r) {
return T[p].first;
}
pushdown(p);
if(mid >= r) {
return queryfr(l , r , p << 1);
}
else if(mid < l) {
return queryfr(l , r , (p << 1) | 1);
}
else {
int ans = queryfr(l , mid , p << 1);
if(ans == -1) {
return queryfr(mid + 1 , r , (p << 1) | 1);
}
else {
return ans;
}
}
}
int queryed(int l , int r , int p) {
int mid = (T[p].l + T[p].l) >> 1;
if(T[p].l == l && T[p].r == r) {
return T[p].ends;
}
pushdown(p);
if(mid >= r) {
return queryed(l , r , p << 1);
}
else if(mid < l) {
return queryed(l , r , (p << 1) | 1);
}
else {
int ans = queryed(mid + 1 , r , (p << 1) | 1);
if(ans == -1) {
return queryed(l , mid , p << 1);
}
else {
return ans;
}
}
}
void updata(int l , int r , int p , int ad) {
int mid = (T[p].l + T[p].r) >> 1;
if(T[p].l == l && T[p].r == r) {
if(ad == 1) {
T[p].add = 1;
T[p].num = T[p].r - T[p].l + 1;
T[p].first = -1;
T[p].ends = -1;
return ;
}
if(ad == -1) {
T[p].add = -1;
T[p].num = 0;
T[p].first = T[p].l;
T[p].ends = T[p].r;
return ;
}
}
pushdown(p);
if(mid >= r) {
updata(l , r , p << 1 , ad);
}
else if(mid < l) {
updata(l , r , (p << 1) | 1 , ad);
}
else {
updata(l , mid , p << 1 , ad);
updata(mid + 1 , r , (p << 1) | 1 , ad);
}
pushup(p);
}
int bisearch(int sta , int sum) {
int l = sta , r = n;
int ans = n;
while(l <= r) {
int mid = (l + r) >> 1;
int gg = query(sta , mid , 1);
gg = mid - sta + 1 - gg;
if(gg >= sum) {
r = mid - 1;
ans = mid;
}
else {
l = mid + 1;
}
}
return ans;
}
int main() {
int t;
scanf("%d" , &t);
while(t--) {
scanf("%d%d" , &n , &m);
build(1 , n , 1);
for(int i = 1 ; i <= m ; i++) {
int k , a , f;
scanf("%d%d%d" , &k , &a , &f);
if(k == 1) {
a++;
int res = query(a , n , 1);
res = n - a + 1 - res;
if(res == 0) {
printf("Can not put any one.\n");
continue;
}
int sum = min(res , f);
int ed = bisearch(a , sum);
int fr = queryfr(a , ed , 1);
updata(fr , ed , 1 , 1);
printf("%d %d\n" , fr - 1 , ed - 1);
}
if(k == 2) {
a++ , f++;
int res = query(a , f , 1);
updata(a , f , 1 , -1);
printf("%d\n" , res);
}
}
printf("\n");
}
return 0;
}
hdu 4614 Vases and Flowers(线段树)的更多相关文章
- HDU 4614 Vases and Flowers(线段树+二分)
题目链接 比赛的时候一直想用树状数组,但是树状数组区间更新之后,功能有局限性.线段树中的lz标记很强大,这个题的题意也挺纠结的. k = 1时,从a开始,插b个花,输出第一个插的位置,最后一个的位置, ...
- hdu 4614 Vases and Flowers 线段树
题目链接 一共n个盒子, 两种操作, 第一种是给出两个数x, y, 从第x个盒子开始放y朵花, 一个盒子只能放一朵, 如果某个盒子已经有了, 那么就跳过这个盒子放下面的盒子. 直到花放完了或者到了最后 ...
- HDU 4614 Vases and Flowers(线段树+二分)
Vases and Flowers Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others ...
- HDU 4614 Vases and Flowers (2013多校2 1004 线段树)
Vases and Flowers Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others ...
- HDU 4614 Vases and Flowers(二分+线段树区间查询修改)
描述Alice is so popular that she can receive many flowers everyday. She has N vases numbered from 0 to ...
- HDU 4614 Vases and Flowers(线段树+记录区间始末点或乱搞)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4614 题目大意:有n个空花瓶,有两种操作: 操作①:给出两个数字A,B,表示从第A个花瓶开始插花,插B ...
- hdu 4614 Vases and Flowers(线段树:成段更新)
线段树裸题.自己写复杂了,准确说是没想清楚就敲了. 先是建点为已插花之和,其实和未插花是一个道理,可是开始是小绕,后来滚雪球了,跪了. 重新建图,分解询问1为:找出真正插画的开始点和终止点,做成段更新 ...
- HDU 4614 Vases and Flowers (2013多校第二场线段树)
题意摘自:http://blog.csdn.net/kdqzzxxcc/article/details/9474169 ORZZ 题意:给你N个花瓶,编号是0 到 N - 1 ,初始状态花瓶是空的,每 ...
- HDU 4614 Vases and Flowers 【线段树】+【二分】
<题目链接> 题目大意: 有n个花瓶,每个花瓶中只能放一朵花.两种操作,一种是从A开始放F朵花,如果有的花瓶中已经有花则跳过这个花瓶,往下一个花瓶放:第二种是将区间[A,B]之间花瓶中的花 ...
- hdu 4614 Vases and Flowers
http://acm.hdu.edu.cn/showproblem.php?pid=4614 直接线段树维护 代码: #include<iostream> #include<cstd ...
随机推荐
- .net core开发从未如此简单,比abp更接地气
在谈起java一家独大的时候,dotnet人员总是一边嘲笑大量滥竽充数的java从业者,一边羡慕人家的生态.以前是只能羡慕,现在dotnet core开源了,我们都可以为dotnet core的开原生 ...
- Okhttp3 网络请求框架与 Gson
Maven环境 : <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>o ...
- 利用反射,更改string对象的value数组以达到改变string值。
package test; import java.lang.reflect.Field; import lombok.Value; public class Test1{ public static ...
- 线性分类 Linear Classification
软分类:y 的取值只有正负两个离散值,例如 {0, 1} 硬分类:y 是正负两类区间中的连续值,例如 [0, 1] 一.感知机 主要思想:分错的样本数越少越好 用指示函数统计分错的样本数作为损失函数, ...
- String与new String()的区别
JVM为了提升性能和减少内存开销,避免字符串的重复创建,维护了一块特殊的内存空间——字符串实例池. String赋值的两种方式. 1.String str = "test"; 以这 ...
- 二.Google黑客语法
搜索也是一门艺术! 说起Google,可谓是无人不知无人不晓,其强大的搜索功能,可以让你在瞬间找到你想要的一切.对于黑客而言,Google可是 一款绝佳的黑客工具.正因Google强大的检索能力,黑客 ...
- Netty源码分析--内存模型(上)(十一)
前两节我们分别看了FastThreadLocal和ThreadLocal的源码分析,并且在第八节的时候讲到了处理一个客户端的接入请求,一个客户端是接入进来的,是怎么注册到多路复用器上的.那么这一节我们 ...
- 入门MySQL——查询语法练习
前言: 前面几篇文章为大家介绍了DML以及DDL语句的使用方法,本篇文章将主要讲述常用的查询语法.其实MySQL官网给出了多个示例数据库供大家实用查询,下面我们以最常用的员工示例数据库为准,详细介绍各 ...
- 解决 Nginx 代理Apex慢的问题
前不久用 Nginx 代理 Oracle 的 Apex 速度非常慢,我之前Nginx 配置如下: server{ listen 80; server_name localhost; client_ma ...
- 基于Springboot的BaseService和BaseController
基于Springboot的BaseService,BaseController 前言: 在做项目时需要对大量的表做增删查改,而其中的逻辑大同小异,所以抽象了一个 BaseService,BaseCon ...