开两个线段树,分别查询。
注意题面中给出的单引号是中文的,记得要改,不然WA哭。
具体来说,我们开一颗女神树与屌丝树,维护区间和,区间紧靠左右端点的最大值(连续的1),对于屌丝的操作在屌丝树中查找修改,对于女神来说为了不打扰屌丝的时间,我们先在屌丝树中查找时间看是否可以不占用屌丝时间,否则我们再在女神树中找。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+7;
typedef long long ll;
int sumn[maxn<<2|1];
int lmaxn[maxn<<2|1];
int rmaxn[maxn<<2|1];
int datn[maxn<<2|1];
int lazyn[maxn<<2|1];
int sumd[maxn<<2|1];
int lmaxd[maxn<<2|1];
int rmaxd[maxn<<2|1];
int datd[maxn<<2|1];
int lazyd[maxn<<2|1];
void pushupn(int l,int r,int k){
int mid=(l+r)>>1;
sumn[k]=sumn[k<<1]+sumn[k<<1|1];
lmaxn[k]=lmaxn[k<<1];
if(sumn[k<<1]==mid-l+1) lmaxn[k]=max(lmaxn[k],sumn[k<<1]+lmaxn[k<<1|1]);
rmaxn[k]=rmaxn[k<<1|1];
if(sumn[k<<1|1]==r-mid) rmaxn[k]=max(rmaxn[k],sumn[k<<1|1]+rmaxn[k<<1]);
datn[k]=max(max(datn[k<<1],datn[k<<1|1]),rmaxn[k<<1]+lmaxn[k<<1|1]);
}
void pushupd(int l,int r,int k){
int mid=(l+r)>>1;
sumd[k]=sumd[k<<1]+sumd[k<<1|1];
lmaxd[k]=lmaxd[k<<1];
if(sumd[k<<1]==mid-l+1) lmaxd[k]=max(lmaxd[k],sumd[k<<1]+lmaxd[k<<1|1]);
rmaxd[k]=rmaxd[k<<1|1];
if(sumd[k<<1|1]==r-mid) rmaxd[k]=max(rmaxd[k],sumd[k<<1|1]+rmaxd[k<<1]);
datd[k]=max(max(datd[k<<1],datd[k<<1|1]),rmaxd[k<<1]+lmaxd[k<<1|1]);
}
void pushdownn(int l,int r,int k){
if(lazyn[k]!=-1){
int mid=(l+r)>>1;
lazyn[k<<1]=lazyn[k<<1|1]=lazyn[k];
sumn[k<<1]=lmaxn[k<<1]=rmaxn[k<<1]=datn[k<<1]=(mid-l+1)*lazyn[k];
sumn[k<<1|1]=lmaxn[k<<1|1]=rmaxn[k<<1|1]=datn[k<<1|1]=(r-mid)*lazyn[k];
lazyn[k]=-1;
}
}
void pushdownd(int l,int r,int k){
if(lazyd[k]!=-1){
int mid=(l+r)>>1;
lazyd[k<<1]=lazyd[k<<1|1]=lazyd[k];
sumd[k<<1]=lmaxd[k<<1]=rmaxd[k<<1]=datd[k<<1]=(mid-l+1)*lazyd[k];
sumd[k<<1|1]=lmaxd[k<<1|1]=rmaxd[k<<1|1]=datd[k<<1|1]=(r-mid)*lazyd[k];
lazyd[k]=-1;
}
}
void build(int l,int r,int k){
lazyd[k]=lazyn[k]=-1;
sumn[k]=sumd[k]=datd[k]=datn[k]=lmaxd[k]=lmaxn[k]=rmaxd[k]=rmaxn[k]=r-l+1;
if(l==r) return ;
int mid=(l+r)>>1;
build(l,mid,k<<1);
build(mid+1,r,k<<1|1);
}
//1女,0男;
void updata(int l,int r,int k,int L,int R,int val,int id){
if(l>=L&&r<=R){
if(id){
sumn[k]=lmaxn[k]=rmaxn[k]=datn[k]=(r-l+1)*val;
lazyn[k]=val;
}
else{
sumd[k]=lmaxd[k]=rmaxd[k]=datd[k]=(r-l+1)*val;
lazyd[k]=val;
}
return ;
}
int mid=(l+r)>>1;
if(id) pushdownn(l,r,k);
else pushdownd(l,r,k);
if(L<=mid) updata(l,mid,k<<1,L,R,val,id);
if(R>mid) updata(mid+1,r,k<<1|1,L,R,val,id);
if(id) pushupn(l,r,k);
else pushupd(l,r,k);
}
//1女,0男;
int myfind(int l,int r,int k,int x,int id){
if(id){
if(l==r){
if(x==1&&sumn[k]) return l;
return 0;
}
int mid=(l+r)>>1;
pushdownn(l,r,k);
if(datn[k<<1]>=x) return myfind(l,mid,k<<1,x,id);
else if(rmaxn[k<<1]+lmaxn[k<<1|1]>=x) return mid-rmaxn[k<<1]+1;
else if(datn[k<<1|1]>=x) return myfind(mid+1,r,k<<1|1,x,id);
pushupn(l,r,k);
return 0;
}
else{
if(l==r){
if(x==1&&sumd[k]) return l;
return 0;
}
int mid=(l+r)>>1;
pushdownd(l,r,k);
if(datd[k<<1]>=x) return myfind(l,mid,k<<1,x,id);
else if(rmaxd[k<<1]+lmaxd[k<<1|1]>=x) return mid-rmaxd[k<<1]+1;
else if(datd[k<<1|1]>=x) return myfind(mid+1,r,k<<1|1,x,id);
pushupd(l,r,k);
return 0;
}
}
char s[9];
int main(){
int T,n,q;
scanf("%d",&T);
int cc=0;
int l,r;
while(T--){
scanf("%d%d",&n,&q);
build(1,n,1);
printf("Case %d:\n",++cc);
while(q--){
scanf("%s%d",s,&l);
if(s[0]=='D'){
int x=myfind(1,n,1,l,0);
if(x){
updata(1,n,1,x,x+l-1,0,0);
printf("%d,let's fly\n",x);
}
else{
printf("fly with yourself\n");
}
}
else if(s[0]=='N'){
int x=myfind(1,n,1,l,0);
if(x){
updata(1,n,1,x,x+l-1,0,0);
updata(1,n,1,x,x+l-1,0,1);
printf("%d,don't put my gezi\n",x);
}
else{
x=myfind(1,n,1,l,1);
if(x){
updata(1,n,1,x,x+l-1,0,0);
updata(1,n,1,x,x+l-1,0,1);
printf("%d,don't put my gezi\n",x);
}
else{
printf("wait for me\n");
}
}
}
else if(s[0]=='S'){
scanf("%d",&r);
updata(1,n,1,l,r,1,0);
updata(1,n,1,l,r,1,1);
printf("I am the hope of chinese chengxuyuan!!\n");
}
}
}
return 0;
}