HDU 4614 Vases and Flowers(线段树+记录区间始末点或乱搞)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4614
题目大意:有n个空花瓶,有两种操作:
操作①:给出两个数字A,B,表示从第A个花瓶开始插花,插B朵花,输出第一个和最后一个插入的花瓶,如果任意花瓶都已经满了不能插花,则输出“Can not put any one.”。
操作②:给出两个数字A,B,表示清空第A~B个花瓶,并输出清空掉的花朵数目。
解题思路:线段树,关于操作②,很简单弄个sum表示区间空花瓶数,计算时清空掉的花朵数=区间长度-sum。
关于操作①,有两种解法,第一种就是记录更新每个区间的空花瓶的始末点,这样在插花时可以由此直接获得起点终点。
第二种,就是乱搞,查找全空区间(都是空花瓶)然后插花,全空区间起点终点的获得就不用说了吧。复杂度真的是玄学(感觉完全算不出来),还以为会超时的,竟然比解法一还快点。。。
解法一:
#include<stdio.h>
#include<algorithm>
#define LC(a) ((a<<1))
#define RC(a) ((a<<1)+1)
#define MID(a,b) ((a+b)>>1)
using namespace std;
typedef long long ll;
const int N = 5e4 + ; struct node {
ll l, r;
ll sum, Start, End, color;//Start是第一个空花瓶位置,End是最后一个空花瓶位置,color=-1,0,1代表初始化,清空,插花
}tree[N<<]; ll leave, Start, sum, End;
void pushup(ll p) {
//维护区间空花瓶数量
tree[p].sum = tree[LC(p)].sum + tree[RC(p)].sum;
tree[p].color = (tree[LC(p)].color == tree[RC(p)].color ? tree[LC(p)].color : -);
//维护空花瓶起点和终点
if (tree[LC(p)].Start != )
tree[p].Start = tree[LC(p)].Start;
else if (tree[LC(p)].End != )
tree[p].Start = tree[LC(p)].End;
else if (tree[RC(p)].Start != )
tree[p].Start = tree[RC(p)].Start;
else if (tree[RC(p)].End != )
tree[p].Start = tree[RC(p)].End;
else
tree[p].Start = ;
tree[p].End = max(max(tree[LC(p)].Start, tree[LC(p)].End), max(tree[RC(p)].Start, tree[RC(p)].End));
} void pushdown(ll p) {
if (tree[p].color == ) {
tree[LC(p)].sum = tree[LC(p)].r - tree[LC(p)].l + ;
tree[LC(p)].Start = tree[LC(p)].l;
tree[LC(p)].End = tree[LC(p)].r;
tree[RC(p)].sum = tree[RC(p)].r - tree[RC(p)].l + ;
tree[RC(p)].Start = tree[RC(p)].l;
tree[RC(p)].End = tree[RC(p)].r;
tree[LC(p)].color = tree[RC(p)].color = ;
}
else if (tree[p].color == ) {
tree[LC(p)].sum = tree[LC(p)].Start = tree[LC(p)].End = tree[RC(p)].sum = tree[RC(p)].Start = tree[RC(p)].End = ;
tree[LC(p)].color = tree[RC(p)].color = ;
}
} void build(ll p, ll l, ll r) {
tree[p].l = l;
tree[p].r = r;
tree[p].Start = tree[p].End = ;
tree[p].sum = ;
if (l == r) {
tree[p].Start = tree[p].End = l;
tree[p].sum = ;
tree[p].color = -;
return;
}
build(LC(p), l, MID(l, r));
build(RC(p), MID(l, r) + , r);
pushup(p);
}
//清空
void update(ll p, ll l, ll r) {
if (r<tree[p].l || l>tree[p].r)
return;
if (l <= tree[p].l&&r >= tree[p].r) {
sum += (tree[p].r - tree[p].l + - tree[p].sum);
tree[p].Start = tree[p].l;
tree[p].End = tree[p].r;
tree[p].sum = tree[p].r - tree[p].l + ;
tree[p].color = ;
return;
}
pushdown(p);
update(LC(p), l, r);
update(RC(p), l, r);
pushup(p);
}
//插花
void query(ll p, ll l, ll r) {
if (r<tree[p].l || l>tree[p].r)
return;
if (leave == || tree[p].sum == )
return;
if (l <= tree[p].l&&r >= tree[p].r) {
if (Start == )
Start = tree[p].Start;
if (leave >= tree[p].sum) {
leave -= tree[p].sum;
End = max(End, tree[p].End);
tree[p].sum = tree[p].Start = tree[p].End = ;
tree[p].color = ;
return;
}
}
pushdown(p);
query(LC(p), l, r);
query(RC(p), l, r);
pushup(p);
}
int main() {
ll q;
scanf("%I64d",&q);
while (q--) {
ll n, m;
scanf("%I64d %I64d",&n,&m);
build(, , n);
while (m--) {
ll k;
scanf("%I64d",&k);
//插花
if (k == ) {
ll a, f;
scanf("%I64d %I64d",&a,&f);
End = Start = ;
leave = f;
query(, a + , n);
if (Start == )
printf("Can not put any one.\n");
else
printf("%I64d %I64d\n",Start-,End-);
}
//清空
else {
ll a, b;
scanf("%I64d %I64d",&a,&b);
sum = ;
update(, a + , b + );
printf("%I64d\n",sum);
}
}
printf("\n");
}
return ;
}
解法二:
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<string>
#define LC(a) (a<<1)
#define RC(a) (a<<1|1)
#define MID(a,b) ((a+b)>>1)
using namespace std;
typedef long long LL;
const int INF=0x3f3f3f3f;
const int N=5e4+; int ans,x,Start,End,flag; struct node{
int sum,l,r;//sum表示空花瓶数
}tree[*N]; void pushdown(int p){
//全满
if(tree[p].sum==tree[p].r-tree[p].l+){
tree[LC(p)].sum=tree[LC(p)].r-tree[LC(p)].l+;
tree[RC(p)].sum=tree[RC(p)].r-tree[RC(p)].l+;
}
//全空
else if(tree[p].sum==)
tree[LC(p)].sum=tree[RC(p)].sum=;
} void pushup(int p){
tree[p].sum=tree[LC(p)].sum+tree[RC(p)].sum;
} void build(int p,int l,int r){
tree[p].l=l;
tree[p].r=r;
if(l==r){
tree[p].sum=;
return;
}
build(LC(p),l,MID(l,r));
build(RC(p),MID(l,r)+,r);
pushup(p);
} void update(int p,int l,int r){
if(l>tree[p].r||r<tree[p].l)
return;
if(x<=)
return;
if(l<=tree[p].l&&r>=tree[p].r){
if(tree[p].sum==)
return;
//找到全空区间
if(x>=tree[p].sum&&tree[p].sum==tree[p].r-tree[p].l+){
if(flag==){
Start=tree[p].l;
flag++;
}
x-=tree[p].sum;
tree[p].sum=;
End=tree[p].r;
return;
}
}
pushdown(p);
update(LC(p),l,r);
update(RC(p),l,r);
pushup(p);
} void query(int p,int l,int r){
if(l>tree[p].r||r<tree[p].l)
return;
if(l<=tree[p].l&&r>=tree[p].r){
ans+=tree[p].r-tree[p].l+-tree[p].sum;
tree[p].sum=tree[p].r-tree[p].l+;
return;
}
pushdown(p);
query(LC(p),l,r);
query(RC(p),l,r);
pushup(p);
} int main(){
int T;
scanf("%d",&T);
while(T--){
int n,q;
scanf("%d%d",&n,&q);
build(,,n-);
while(q--){
int op;
scanf("%d",&op);
if(op==){
int l;
scanf("%d%d",&l,&x);
flag=;
update(,l,n-);
if(flag==)
printf("Can not put any one.\n");
else
printf("%d %d\n",Start,End);
}
else{
int l,r;
scanf("%d%d",&l,&r);
ans=;
query(,l,r);
printf("%d\n",ans);
}
}
printf("\n");
}
return ;
}
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 (2013多校第二场线段树)
题意摘自:http://blog.csdn.net/kdqzzxxcc/article/details/9474169 ORZZ 题意:给你N个花瓶,编号是0 到 N - 1 ,初始状态花瓶是空的,每 ...
- HDU-4614 Vases and Flowers 线段树区间更新
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4614 线段树保存区间是否被覆盖以及区间的和即可,在询问的时候在线段树上二分查找就可以了...代码写得比 ...
- hdu4614 Vases and Flowers 线段树+二分
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4614 题意: 给你N个花瓶,编号是0 到 N - 1 ,初始状态花瓶是空的,每个花瓶最多插一朵花. ...
- hdu4614 Vases and Flowers 线段树
Alice is so popular that she can receive many flowers everyday. She has N vases numbered from 0 to N ...
- hdu 1754 I Hate It (线段树求区间最值)
HDU1754 I Hate It Time Limit:3000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u D ...
- 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 ...
随机推荐
- 基于数组实现Java 自定义Stack栈类及应用
栈是存放对象的一种特殊容器,在插入与删除对象时,这种结构遵循后进先出( Last-in-first-out,LIFO)的原则.java本身是有自带Stack类包,为了达到学习目的已经更好深入了解sta ...
- 【JQuery】数据
一.前言 接着前一章的内容,继续本章的学习 二.内容 queue 显示或操作在匹配元素上执行的函数队列 .queue(queueName) 操作在匹配元素上执行的函数队列 .queue( ...
- 【BZOJ4300】绝世好题(动态规划)
[BZOJ4300]绝世好题(动态规划) 题面 BZOJ Description 给定一个长度为n的数列ai,求ai的子序列bi的最长长度,满足bi&bi-1!=0(2<=i<=l ...
- 【bzoj4894】天赋
Portal-->bzoj4894 Solution 这题的话其实,一句话题意就是求..外向树(方向是根往叶子).. 然后关于有向图的生成树计数的话,求外向树就是将度数矩阵改成入度,内向树就是改 ...
- 【题解】Points, Lines and Ready-made Titles Codeforces 871C 图论
Prelude 真是一道好题,然而比赛的时候花了太多时间在B题上,没时间想这个了QAQ. 题目链接:萌萌哒传送门(.^▽^) Solution 观察样例和样例解释,我们发现,假如有四个点,恰好占据在某 ...
- 使用jvisualvm工具来监控java运行情况
jvisualvm是jdk自带的工具.所以要先安装jdk 1.jvisualvm工具的路径: 通过which jvisualvm来查看 /usr/local/jdk1.7.0_79/bin/jvi ...
- git查看/修改 用户名和邮箱
用户名和邮箱地址的作用 用户名和邮箱地址是本地git客户端的一个变量,不随git库而改变. 每次commit都会用用户名和邮箱纪录. github的contributions统计就是按邮箱来统计的. ...
- Python学习笔记(四十八)POP3收取邮件
收取邮件就是编写一个MUA作为客户端,从MDA把邮件获取到用户的电脑或者手机上.收取邮件最常用的协议是POP协议,目前版本号是3,俗称POP3. Python内置一个poplib模块,实现了POP3协 ...
- ubuntu11下安装文件
1.ubuntu11下安装.run文件 首先右键单击这个文件,在properties-permissions那里选择允许以程序执行(打钩Allow executing file as program) ...
- Selenium/HtmlUnit设置代理获取JS生成的网页
通常我们使用Java提供的HttpURLConnection或者Apache的HttpClient获取的网页源代码都是直观可见的,其代码的内容和通过浏览器右键网页->点击查看网页源代码的内容一致 ...