题意:
给你n 个花瓶,每个花瓶只能放一朵花。两种操作
操作1:
给你f 朵花, 从a位置开始放,如果空花瓶不够了,或者花放完了, 就不放了。 输出 放的第一朵的花的位置 和最后一朵花的位置。
操作2:
给定区间[a,b] 将这个区间内的花瓶清空, 输出扔花的数量。
思路:
操作2很好处理, 先查询这个区间花的数量(有花可以设置为1,没花为0), 在区间修改。 即为 区间赋值和区间求和的线段树。
操作1:
根据求区间和 二分第一个放花的位置pos1, 在根据pos1,二分最后一个放花的位置 pos2.
pos2 二分起来或许比较麻烦。
只要保证每次二分只查一次就好了, (查多了 可能会超时)
#include
#include
#include
using namespace std;
int T;
const int maxn = 50000 + 10;
int setv[maxn<<2];
int sum[maxn<<2];
void pushdown(int o,int l,int r){
if (setv[o] != -1){
int m = l + r >> 1;
int lson = o<<1;
int rson = o<<1|1;
setv[lson] = setv[rson] = setv[o];
sum[lson] = setv[o] * (m-l+1);
sum[rson] = setv[o] * (r-m);
setv[o] = -1;
}
}
void pushup(int o){
sum[o] = sum[o<<1] + sum[o<<1|1];
}
int query(int L,int R,int l,int r,int o){
if (L <= l && r <= R){
return sum[o];
}
int m = l + r >> 1;
pushdown(o,l,r);
int ans = 0;
if (m >= L){
ans += query(L,R,l,m,o<<1);
}
if (m < R){
ans += query(L,R,m+1,r,o<<1|1);
}
pushup(o);
return ans;
}
void update(int L,int R,int c,int l,int r,int o){
if (L <= l && r <= R){
setv[o] = c;
sum[o] = c * (r-l+1);
return;
}
pushdown(o,l,r);
int m = l + r >> 1;
if (m >= L ){
update(L,R, c,l,m,o<<1);
}
if (m < R){
update(L,R,c,m+1,r,o<<1|1);
}
pushup(o);
}
int n,q;
void solve(int a,int f){
int l = a,r = n-1;
if (query(a,n,0,n-1,1) == n-a) {
puts("Can not put any one.");
return;
}
int pos1 = 1;
while(l <= r){
int m = l + r >> 1;
int t = query(a,m,0,n-1,1);
if (t == m-a+1) l = m + 1;
else {
r = m - 1;
}
}
pos1 = l;
l = pos1;
r = n-1;
int pos2 = 1;
int t = query(pos1, n-1, 0,n-1,1);
if (n-pos1 - t < f) f = n-pos1-t;
// printf("f = %d\n", query(2,4,0,n-1,1));
while(l <= r) {
int m = l + r >> 1;
int t = query(pos1, m, 0, n-1 , 1);
if (m - pos1 + 1 - t > f) {
r = m - 1;
// pos2 = m;
}
else if (m - pos1 + 1 - t == f){
r = m - 1;
pos2 = m;
}
else {
l = m + 1;
pos2 = m;
}
}
printf("%d %d\n", pos1,l);
update(pos1,l,1,0,n-1,1);
}
int main(){
scanf("%d",&T);
while(T--){
memset(setv,-1,sizeof setv);
memset(sum,0,sizeof sum);
scanf("%d %d", &n, &q);
while(q--){
int op;
scanf("%d",&op);
if (op == 1){
int a,f;
scanf("%d %d",&a, &f);
solve(a,f);
}
else {
int a,b;
scanf("%d %d",&a, &b);
printf("%d\n", query(a,b,0,n-1,1));
update(a,b,0,0,n-1,1);
}
}
puts("");
}
return 0;
}