传送门
题意:编号为 0 ~ n - 1 个花瓶,有两个操作
(1)以 a 为起点,选择之后的 k 个花瓶放上花,输出左右端点。
(2)清空 l ~ r 的所有花瓶中的花,输出清除的花数量
对于第二个操作就是线段树区间赋值和区间查询了。
第一个操作如果知道左右端点直接区间赋值即可。现在问题是怎么求左右端点。比较显然可以在线段树上进行二分,分别二分出来第一个数位置和最后一个数位置。如果填不满k个的话显然第二个答案是INF,不会被更新。那么就需要把k改成 l ~ n - 1 中空花瓶个数,再二分一次就行了。
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define Mid (tr[u].l+tr[u].r>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define pb push_back
#define mk make_pair
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
const int N=1000010,mod=1e9+7,INF=0x3f3f3f3f;
const double eps=1e-6;
int n,m;
struct Node
{
int l,r;
int sum,lazy;
}tr[N<<2];
void pushup(int u)
{
tr[u].sum=tr[L].sum+tr[R].sum;
}
void pushdown(int u)
{
if(tr[u].lazy==-1) return;
tr[L].lazy=tr[R].lazy=tr[u].lazy;
tr[L].sum=Len(L)*tr[u].lazy;
tr[R].sum=Len(R)*tr[u].lazy;
tr[u].lazy=-1;
}
void build(int u,int l,int r)
{
tr[u]={l,r,0,-1};
if(l==r)
{
tr[u].sum=1;
return;
}
build(L,l,Mid),build(R,Mid+1,r);
pushup(u);
}
void modify(int u,int l,int r,int c)
{
if(tr[u].l>=l&&tr[u].r<=r)
{
tr[u].sum=Len(u)*c;
tr[u].lazy=c;
return;
}
pushdown(u);
if(l<=Mid) modify(L,l,r,c);
if(r>Mid) modify(R,l,r,c);
pushup(u);
}
int query(int u,int l,int r)
{
if(tr[u].l>=l&&tr[u].r<=r) return tr[u].sum;
pushdown(u);
int ans=0;
if(l<=Mid) ans+=query(L,l,r);
if(r>Mid) ans+=query(R,l,r);
return ans;
}
void solve(int LL,int C)
{
int l=LL,r=n-1,ans1=INF,ans2=INF;
while(l<=r)
{
int mid=l+r>>1;
if(query(1,l,mid)>=1) r=mid-1,ans1=mid;
else l=mid+1;
}
l=LL,r=n-1;
while(l<=r)
{
int mid=l+r>>1;
int c=query(1,l,mid);
if(c>=C) r=mid-1,ans2=mid;
else C-=c,l=mid+1;
}
if(ans1==INF&&ans2==INF) puts("Can not put any one.");
else
{
if(ans2==INF)
{
C=query(1,LL,n-1);
l=LL,r=n-1;
while(l<=r)
{
int mid=l+r>>1;
int c=query(1,l,mid);
if(c>=C) r=mid-1,ans2=mid;
else C-=c,l=mid+1;
}
}
printf("%d %d\n",ans1,ans2);
modify(1,ans1,ans2,0);
}
}
//0 1 2 3 4 5 6 7 8 9
//0 0 1 1 1 1 0 0 0 0
int main()
{
// ios::sync_with_stdio(false);
// cin.tie(0);
int _; scanf("%d",&_); int T=0;
while(_--)
{
scanf("%d%d",&n,&m);
build(1,0,n-1);
while(m--)
{
int op,l,r; scanf("%d%d%d",&op,&l,&r);
if(op==1) solve(l,r);
else
{
printf("%d\n",r-l+1-query(1,l,r));
modify(1,l,r,1);
}
}
puts("");
}
return 0;
}
/*
*/