题目链接: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(线段树+记录区间始末点或乱搞)的更多相关文章

  1. HDU 4614 Vases and Flowers(线段树+二分)

    题目链接 比赛的时候一直想用树状数组,但是树状数组区间更新之后,功能有局限性.线段树中的lz标记很强大,这个题的题意也挺纠结的. k = 1时,从a开始,插b个花,输出第一个插的位置,最后一个的位置, ...

  2. hdu 4614 Vases and Flowers 线段树

    题目链接 一共n个盒子, 两种操作, 第一种是给出两个数x, y, 从第x个盒子开始放y朵花, 一个盒子只能放一朵, 如果某个盒子已经有了, 那么就跳过这个盒子放下面的盒子. 直到花放完了或者到了最后 ...

  3. HDU 4614 Vases and Flowers (2013多校第二场线段树)

    题意摘自:http://blog.csdn.net/kdqzzxxcc/article/details/9474169 ORZZ 题意:给你N个花瓶,编号是0 到 N - 1 ,初始状态花瓶是空的,每 ...

  4. HDU-4614 Vases and Flowers 线段树区间更新

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4614 线段树保存区间是否被覆盖以及区间的和即可,在询问的时候在线段树上二分查找就可以了...代码写得比 ...

  5. hdu4614 Vases and Flowers 线段树+二分

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4614 题意: 给你N个花瓶,编号是0  到 N - 1 ,初始状态花瓶是空的,每个花瓶最多插一朵花. ...

  6. hdu4614 Vases and Flowers 线段树

    Alice is so popular that she can receive many flowers everyday. She has N vases numbered from 0 to N ...

  7. hdu 1754 I Hate It (线段树求区间最值)

    HDU1754 I Hate It Time Limit:3000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u D ...

  8. HDU 4614 Vases and Flowers(线段树+二分)

    Vases and Flowers Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others ...

  9. 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 ...

随机推荐

  1. Eclipse如何将代码变成大写/小写

    代码变小写:选中要换的代码,操作Ctrl+Shift+y即可将大写变小写 代码变大写:选中要换的代码,操作Ctrl+Shift+x即可将小写变大写

  2. 【BZOJ2727】双十字(动态规划,树状数组)

    [BZOJ2727]双十字(动态规划,树状数组) 题面 BZOJ 洛谷 题解 我们去年暑假的时候考试考过. 我当时写了个大暴力混了\(70\)分.... 大暴力是这么写的: 预处理每个位置向左右/上/ ...

  3. MSSQL DBA权限获取WEBSHELL的过程

    前言 本文主要通过一个案例来演示一下当MSSQL是DBA权限,且不知道路径的时候如何去获取WEBSHELL.当然这种方式对站库分离的无效.我测试的环境是在Win7 64位下,数据库是SQLServer ...

  4. [HEOI2014]逻辑翻译

    ywy_c_asm的良心题解 是道好题 体现了二进制位的形象递归思想,以及将FWT的思路(都是拆位分治)用到题目中的典范 可以暴力高斯消元.完全没有利用2^N以及+-1的良好性质 发现项数,方程和二进 ...

  5. 【bzoj2788】Festival

    Portal --> bzoj2788 Description 有\(n\)个正整数\(X_1,X_2,...,X_n\),再给出\(m1+m2\)个限制条件,限制分为两类: 1.给出\(a,b ...

  6. 【learning】快速沃尔什变换FWT

    问题描述 已知\(A(x)\)和\(B(x)\),\(C[i]=\sum\limits_{j\otimes k=i}A[j]*B[k]\),求\(C\) 其中\(\otimes\)是三种位运算的其中一 ...

  7. 图像格式转换之BMP格式转换为JPG格式

    // bmp2jpg.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include "jpeglib.h" #inc ...

  8. ICPC 2018 南京网络赛 J Magical Girl Haze(多层图最短路)

    传送门:https://nanti.jisuanke.com/t/A1958 题意:n个点m条边的路,你有k次机会将某条路上的边权变为0,问你最短路径长度 题解:最短路变形,我们需要在常规的最短路上多 ...

  9. Linux上调试core文件(Good)

    coredump文件 什么是coredump? 通常情况下coredmp包含了程序运行时的内存,寄存器状态,堆栈指针,内存管理信息等.可以理解为把程序工作的当前状态存储成一个文件.许多程序和操作系统出 ...

  10. java中16进制转换10进制

    java中16进制转换10进制 public static void main(String[] args) { String str = "04e1"; String myStr ...