题意:给你一排花盆,两种操作:第一种从i开始插花,插j朵,遇到有花的花盆就跳过。直到插完j朵花或者后面没有空花盆为止,输出从哪开始插,插到哪结束的区间。第二种是求i~j区间的花的总数,然后把这个区间的花全部拔掉。
终于自己手写了一个线段树,虽然花了一上午。其实这道题不难,当时求区间的时候j - i + 1,有一个不小心把+写成了-号,花了半上午,然后忽略了起始位置可能有花的情况,又花了半上午,算了,上代码:
其中二分是为了确定起始位置和结束位置,线段树是为了维护 区间。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
using namespace std;
const int MAXN=50050;
int a[MAXN],ans[MAXN<<2],lazy[MAXN<<2];
void PushUp(int rt)
{
ans[rt]=ans[rt<<1]+ans[rt<<1|1];
}
void Build(int l,int r,int rt)
{
if (l==r)
{
ans[rt]=a[l];
return;
}
int mid=(l+r)>>1;
Build(l,mid,rt<<1);
Build(mid+1,r,rt<<1|1);
PushUp(rt);
}
void PushDown(int rt,int ln,int rn)//ln表示左子树元素结点个数,rn表示右子树结点个数
{
if (lazy[rt])
{
if(lazy[rt] == -1) {
lazy[rt<<1]=-1;
lazy[rt<<1|1]=-1;
ans[rt<<1]=0;
ans[rt<<1|1]=0;
lazy[rt]=0;
}
else {
lazy[rt<<1]=1;
lazy[rt<<1|1]=1;
ans[rt<<1]=ln;
ans[rt<<1|1]=rn;
lazy[rt]=0;
}
}
}
void Update(int L,int R,int C,int l,int r,int rt)
{
if (L<=l&&r<=R)
{
if(C == -1) {
ans[rt]=0;
lazy[rt]=-1;
return;
}
else {
ans[rt] = (r - l + 1);
lazy[rt] = 1;
return;
}
}
int mid=(l+r)>>1;
PushDown(rt,mid-l+1,r-mid);
if (L<=mid) Update(L,R,C,l,mid,rt<<1);
if (R>mid) Update(L,R,C,mid+1,r,rt<<1|1);
PushUp(rt);
}
int Query(int L,int R,int l,int r,int rt)
{
if (L<=l&&r<=R)
return ans[rt];
int mid=(l+r)>>1;
PushDown(rt,mid-l+1,r-mid);//若更新只有点更新,不需要这句
int ANS=0;
if (L<=mid) ANS+=Query(L,R,l,mid,rt<<1);
if (R>mid) ANS+=Query(L,R,mid+1,r,rt<<1|1);
return ANS;
}
int main()
{
int T, n, m, p, q, t;
cin >> T;
while(T--) {
cin >> n >> m;
memset(a, 0, sizeof(a));
memset(ans, 0, sizeof(ans));
memset(lazy, 0, sizeof(lazy));
while(m--) {
cin >> p >> q >> t;
q++;
t;
if(p == 1) {
int l = q;
int r = n;
int c;
if(Query(q, q, 1, n, 1)) {
c = l - Query(1, l, 1, n, 1);
while(l < r) {
int mid = (l + r) / 2;
if(mid - Query(1, mid, 1, n, 1) != c) {
r = mid;
}
else {
l = mid + 1;
}
}
q = r;
}
l = q;
r = n;
while(l < r) {
int mid = (l + r) / 2;
if(mid - q + 1 - Query(q, mid, 1, n, 1) >= t) {
r = mid;
}
else {
l = mid + 1;
}
}
if(r == n) {
if(Query(q, r, 1, n, 1) <= r - q + 1 - t) {
cout << q - 1 << ' ' << r - 1 << endl;
Update(q, r, 1, 1, n, 1);
}
else if(Query(q, r, 1, n, 1) == r - q + 1) {
cout << "Can not put any one.\n";
}
else {
c = r - q + 1 - Query(q, r, 1, n, 1);
l = q;
r = n;
while(l < r) {
int mid = (l + r) / 2;
if(mid - q + 1 - Query(q, mid, 1, n, 1) == c) {
r = mid;
}
else {
l = mid + 1;
}
}
cout << q - 1 << ' ' << r - 1 << endl;
Update(q, r, 1, 1, n, 1);
}
}
else {
cout << q - 1 << ' ' << r - 1 << endl;
Update(q, r, 1, 1, n, 1);
}
}
else {
cout << Query(q, t + 1, 1, n, 1) << endl;
Update(q, t + 1, -1, 1, n, 1);
}
}
cout << endl;
}
return 0;
}