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) ?
//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 ;
}