描述
1~n区间初始全部为1,每次申请一段长为x的连续区间,返回最靠左的起点位置。此题要求维护两个树的最大连续字段和。
分析
记录此题主要还是因为这个区间合并于自己之前写的方式不太一样,查询时先看左子树内是否存在,这样的区间,再去看中间,中间满足就直接返回,最后看右子树。递归结束条件就是当前节点的左端最长大于等于请求的长度。
代码
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<set>
#include<map>
#include<list>
#include<stack>
#include<queue>
#include<vector>
#define cl (k<<1)
#define cr (k<<1|1)
#define Mid ((a[k].l+a[k].r)>>1)
#define mem(a,x) memset(a,x,sizeof(a))
using namespace std;
#define bug printf("???\n")
typedef long long LL;
const int Inf=0x3f3f3f3f;
const double eps=1e-7;
const int maxn=100050;
struct N{
int l,r;
int la,ra,ma;
int lz;
}aa[maxn*4],bb[maxn*4];//aa维护基友和女神时间 bb维护女神时间
void up(N&x,N&y,N&z){
// x.l = y.l, x.r = z.r;
x.la = (y.la==y.r-y.l+1) ? y.la+z.la : y.la;
x.ra = (z.ra==z.r-z.l+1) ? z.ra+y.ra : z.ra;
x.ma = max(max(y.ma, z.ma),y.ra+z.la);
// x.ma = max(max(x.la, x.ra),y.ra+z.la); 这个地方找了半天的bug
}
void down(N *a,int k){
a[cl].lz = a[cr].lz = a[k].lz;
if(a[k].lz==1){
a[cl].la = a[cl].ra = a[cl].ma = a[cl].r-a[cl].l+1;
a[cr].la = a[cr].ra = a[cr].ma = a[cr].r-a[cr].l+1;
}
else{
a[cl].la = a[cl].ra = a[cl].ma = 0;
a[cr].la = a[cr].ra = a[cr].ma = 0;
}
a[k].lz = -1;
}
void build(N *a,int k,int l,int r){
a[k].l=l, a[k].r=r, a[k].lz=-1;
if(l==r){
a[k].la = a[k].ra = a[k].ma = 1;
return;
}
build(a, cl, l, Mid);
build(a, cr, Mid+1, r);
up(a[k],a[cl],a[cr]);
}
int get(N *a,int k,int len){
if(a[k].la>=len) return a[k].l;
if(a[k].ma<len){
return -1;
}
if(a[k].lz!=-1) down(a,k);
if(a[cl].ma>=len) return get(a,cl,len);
if(a[cl].ra+a[cr].la>=len){
return a[cl].r-a[cl].ra+1;
}
//if(a[cr].ma>=len)
return get(a,cr,len);
}
void clear(N *a,int k,int l,int r,int x){
if(l<=a[k].l&&a[k].r<=r){
if(x) a[k].la = a[k].ra = a[k].ma = a[k].r-a[k].l+1;
else a[k].la = a[k].ra = a[k].ma = 0;
a[k].lz = x;
return;
}
if(a[k].lz!=-1) down(a, k);
if(l<=Mid) clear(a, cl,l,r,x);
if(r> Mid) clear(a, cr,l,r,x);
up(a[k],a[cl],a[cr]);
}
int main()
{
int T,time=0;
cin>>T;
while(T--){
int n,m;
char s[10];
cin>>n>>m;
build(aa,1,1,n);
build(bb,1,1,n);
printf("Case %d:\n",++time);
for(int i=1; i<=m; i++){
scanf("%s",s);
int x,y;
if(s[0]=='D'){
scanf("%d",&x);
int tmp=get(aa,1,x);
if(tmp==-1) printf("fly with yourself\n");
else{
printf("%d,let's fly\n",tmp);
clear(aa, 1, tmp, tmp+x-1, 0);
}
}
if(s[0]=='N'){
scanf("%d",&x);
int tmp=get(aa,1,x);
if(tmp==-1) {
tmp = get(bb,1,x);
if(tmp==-1){
printf("wait for me\n"); //俩次没找到
continue;
}
}
printf("%d,don't put my gezi\n",tmp);
clear(aa, 1, tmp, tmp+x-1, 0);
clear(bb, 1, tmp, tmp+x-1, 0);
}
if(s[0]=='S'){
scanf("%d%d",&x,&y);
clear(aa,1,x,y,1);
clear(bb,1,x,y,1);
printf("I am the hope of chinese chengxuyuan!!\n");
}
}
}
}