比较简单,一发A。
这几个操作很明显线段树维护。
初是区间都是0,代表某个区间花数量和
2 a b 把区间赋值成0,查询区间和。
1 a f 查询 a - n-1 区间无花数量是否小于f 小于的花直接全部插上花,插之前询问最左边无花,最右边无花的瓶子位置即最小值最右边//最左 的坐标。
如果区间无花数量大于f。则二分查找区间无花数量第一个大于等于f的位置。刚好这个区间插满花,右边为pos左边为区间最左边无花位置。
//KX
#include
using namespace std;
typedef long long ll;
typedef double db;
const int M = 5e4+7;
#define ls o*2
#define rs o*2+1
#define pb push_back
int st[M<<2],tag[M<<2],mn[M<<2];
void pd(int o,int l,int r)
{
if(tag[o]==-1)return ;
int m=(l+r)/2;
mn[ls]=mn[rs]=tag[ls]=tag[rs]=tag[o];
st[ls]=tag[o]*(m-l+1);
st[rs]=tag[o]*(r-m);
tag[o]=-1;
return ;
}
void bd(int o,int l,int r)
{
mn[o]=st[o]=0,tag[o]=-1;
if(l==r)
{
return ;
}
int m=(l+r)/2;
bd(ls,l,m);
bd(rs,m+1,r);
}
void up(int o,int l,int r,int x,int y,int d)//区间覆盖
{
// printf("%d %d %d %d\n",l,r,x,y);
if(x<=l&&r<=y)
{
mn[o]=d;
st[o]=d*(r-l+1);
tag[o]=d;
return ;
}
pd(o,l,r);
int m=(l+r)/2;
if(x<=m)up(ls,l,m,x,y,d);
if(y>m)up(rs,m+1,r,x,y,d);
mn[o]=min(mn[ls],mn[rs]);
st[o]=st[ls]+st[rs];
}
int qu(int o,int l,int r,int x,int y)//区间和
{
if(x<=l&&r<=y)
{
return st[o];
}
pd(o,l,r);
int m=(l+r)/2;
int ans=0;
if(x<=m)ans+=qu(ls,l,m,x,y);
if(y>m)ans+=qu(rs,m+1,r,x,y);
return ans;
}
bool fl;
int ps;
void qul(int o,int l,int r,int x,int y)//区间最小值 最左边
{
// printf("%d %d %d %d %d\n",l,r,mn[o],x,y);
if(l>y||ry||r=b)//第一个大于等于b
{
pos=mid;
r=mid-1;
}
else
l=mid+1;
}
// puts("zzzz");
up(1,1,n,pl,pos,1);
printf("%d %d\n",pl-1,pos-1);
}
else
{
b++;
int w=qu(1,1,n,a,b);
up(1,1,n,a,b,0);
printf("%d\n",w);
}
}
puts("");
}
return 0;
}
看了网上别人的解法,写了一个纯二分的。这种线段树处理比较简单
只有区间更新,区间赋值。
二分查找第一个无花数量大于1即左边插花位置,第一个无花数量大于要插的花,即右边插花位置
//KX
#include
using namespace std;
typedef long long ll;
typedef double db;
const int M = 5e4+7;
#define ls o*2
#define rs o*2+1
#define pb push_back
int st[M<<2],tag[M<<2],mn[M<<2];
void pd(int o,int l,int r)
{
if(tag[o]==-1)return ;
int m=(l+r)/2;
mn[ls]=mn[rs]=tag[ls]=tag[rs]=tag[o];
st[ls]=tag[o]*(m-l+1);
st[rs]=tag[o]*(r-m);
tag[o]=-1;
return ;
}
void bd(int o,int l,int r)
{
mn[o]=st[o]=0,tag[o]=-1;
if(l==r)
{
return ;
}
int m=(l+r)/2;
bd(ls,l,m);
bd(rs,m+1,r);
}
void up(int o,int l,int r,int x,int y,int d)//区间覆盖
{
// printf("%d %d %d %d\n",l,r,x,y);
if(x<=l&&r<=y)
{
mn[o]=d;
st[o]=d*(r-l+1);
tag[o]=d;
return ;
}
pd(o,l,r);
int m=(l+r)/2;
if(x<=m)up(ls,l,m,x,y,d);
if(y>m)up(rs,m+1,r,x,y,d);
mn[o]=min(mn[ls],mn[rs]);
st[o]=st[ls]+st[rs];
}
int qu(int o,int l,int r,int x,int y)//区间和
{
if(x<=l&&r<=y)
{
return st[o];
}
pd(o,l,r);
int m=(l+r)/2;
int ans=0;
if(x<=m)ans+=qu(ls,l,m,x,y);
if(y>m)ans+=qu(rs,m+1,r,x,y);
return ans;
}
int main()
{
int t,n,q,k,a,b;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&q);
bd(1,1,n);
while(q--)
{
scanf("%d%d%d",&k,&a,&b);
/*for(int i=1;i<=n;i++)
printf("%d ",qu(1,1,n,i,i));
puts("ok");*/
a++;
if(k==1)
{
int w=qu(1,1,n,a,n);
//printf("--- %d\n",w);
w=n-a+1-w;
if(w==0)
{
puts("Can not put any one.");
continue;
}
if(w=1)//第一个大于等于1
{
pl=mid;
r=mid-1;
}
else
l=mid+1;
}
l=pl,r=n;
int pos=n;
while(l<=r)
{
int mid=(l+r)/2;
w=qu(1,1,n,pl,mid);//有花的个数
w=mid-pl+1-w;//无花的个数
if(w>=b)//第一个大于等于b
{
pos=mid;
r=mid-1;
}
else
l=mid+1;
}
// puts("zzzz");
up(1,1,n,pl,pos,1);
printf("%d %d\n",pl-1,pos-1);
}
else
{
b++;
int w=qu(1,1,n,a,b);
up(1,1,n,a,b,0);
printf("%d\n",w);
}
}
puts("");
}
return 0;
}