题目链接:点击链接
题意:
有标号从0到n-1的n个花瓶,每个花瓶只能放一朵花。现在有两种操作,操作一,从第a个花瓶开始,放b朵花进入花瓶,如果能放,输出能放的最左边的位置,和最右边的位置,如果不能放,输出不能放。操作二,将花瓶a到花瓶b这个区间内的花全部丢弃。
思路:
维护区间内花的数量sumv[rt],区间内最左边空花瓶的位置为L[rt],最右边位置为R[rt]。
设花瓶空为0,有花为1,操作一则是要求如何快速将区间内的0改成1。
我们维护了区间内花的总数sumv[rt],先是和以往的update函数一样,确定区间范围,如果当前区间内空花瓶的数量int cha = (r-l+1)-sumv[rt]小于等于待放花数b时,b -= cha。如果cha大于b,我们递归的先放左边,再放右边。
操作二是区间置相同值。
总结:
这道题思路出来很快,但是实现一直有问题,后来发现是没有维护L[]和R[]的值…怕是石乐志。
仍旧wa了。
对拍发现了一个难以理解的细节,build函数明明会把L[], R[], sumv[], setv[]都初始化好,但是我写的程序,上一个样例影响到了当前样例,按理说不会访问到上一个样例残留的数据。
原来setv[]没有初始化好…
代码:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
using namespace std;
const int maxn = 50000 + 100;
const int INF = 0x3f3f3f3f;
int _st, _ed, _sum, _now, t, n, m, opt, aa, bb;
int L[maxn<<2], R[maxn<<2];
int setv[maxn<<2], sumv[maxn<<2]; // sumv is the quantity of flowers
void pushup(int rt){
setv[rt] = -1;
sumv[rt] = sumv[rt<<1] + sumv[rt<<1|1];
L[rt] = min(L[rt<<1], L[rt<<1|1]);
R[rt] = max(R[rt<<1], R[rt<<1|1]);
}
void pushdown(int l, int r, int rt, int len){
if(setv[rt]!=-1){
setv[rt<<1] = setv[rt<<1|1] = setv[rt];
sumv[rt<<1] = (len - len/2) * setv[rt];
sumv[rt<<1|1] = (len/2) * setv[rt];
if(setv[rt]==1){
L[rt<<1] = L[rt<<1|1] = INF;
R[rt<<1] = R[rt<<1|1] = -INF;
}
else{
int mid = (l+r)>>1;
L[rt<<1] = l;
R[rt<<1] = mid;
L[rt<<1|1] = mid+1;
R[rt<<1|1] = r;
}
setv[rt] = -1;
}
}
void build(int rt, int l, int r){
if(l==r){
L[rt] = R[rt] = l;
sumv[rt] = 0;
setv[rt] = -1;
}
else{
int mid = (l+r)>>1;
build(rt<<1, l, mid);
build(rt<<1|1, mid+1, r);
pushup(rt);
}
}
void Set(int rt, int a, int b, int l, int r){
if(_now == 0) return ;
if(a<=l && r<=b){
if(sumv[rt] == (r-l+1)) return; // full of flowers
if(_now <= 0) return; // all flowers are put into vases before current one
int cha = r-l+1 - sumv[rt];
if(cha > _now){
pushdown(l, r, rt, r-l+1);
int mid = (l+r)>>1;
Set(rt<<1, a, b, l, mid);
Set(rt<<1|1, a, b, mid+1, r);
pushup(rt);
}
else{
_now -= cha;
_st = min(_st, L[rt]);
_ed = max(_ed, R[rt]);
setv[rt] = 1;
sumv[rt] = r-l+1;
L[rt] = INF;
R[rt] = -INF;
}
}
else{
pushdown(l, r, rt, r-l+1);
int mid = (l+r)>>1;
if(a<=mid) Set(rt<<1, a, b, l, mid);
if(mid<b) Set(rt<<1|1, a, b, mid+1, r);
pushup(rt);
}
}
void Discard(int rt, int a, int b, int l, int r){
if(a<=l && r<=b){
_sum += sumv[rt];
sumv[rt] = 0;
setv[rt] = 0;
L[rt] = l;
R[rt] = r;
}
else{
pushdown(l, r, rt, r-l+1);
int mid = (l+r)>>1;
if(a<=mid) Discard(rt<<1, a, b, l, mid);
if(mid<b) Discard(rt<<1|1, a, b, mid+1, r);
pushup(rt);
}
}
int main(){
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
scanf("%d", &t);
while(t--){
scanf("%d%d", &n, &m);
// memset(setv, -1, sizeof(setv));
// memset(sumv, 0, sizeof(sumv));
build(1, 1, n);
for(int i=0; i<m; ++i){
scanf("%d%d%d", &opt, &aa, &bb);
if(opt==1){
_st = INF; _ed = -INF; _now = bb;
Set(1, aa+1, n, 1, n);
if(_now == bb){
printf("Can not put any one.\n");
}
else{
printf("%d %d\n", _st-1, _ed-1);
}
}
if(opt==2){
_sum = 0;
Discard(1, aa+1, bb+1, 1, n);
printf("%d\n", _sum);
}
}
printf("\n");
}
return 0;
}