!
题意:
有女神和屌丝两种朋友,屌丝每次申请x时间,女神每次也申请x时间,每次都找最靠左的时间
然后女神优先级高于屌丝,可以覆盖屌丝的时间,但是,如果屌丝被覆盖的不完全,比如 1-5 是屌丝
然后女神占了1-3,剩下的4-5 还是屌丝的。
题解:
正常的线段树区间01维护,然后开两个树,一个维护屌丝的时间,一个维护女神的时间
屌丝就正常在屌丝的树上,维护 更新 ,然后女神的话,现在屌丝树上看 有没有地方 有地方就
更新屌丝树,然后如果没有地方的话 ,在女神树上找一段时间 找到了 在女神树和屌丝树都更新
一下因为有可能女神占用屌丝的时间 ,比之前的屌丝时间还多,所以需要更新一下。
AC代码
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define N 100010
struct node
{
int l,r;
int ls,rs,sum;
int lazy;
};
node shu[2][N<<2];
void pushup(int rt,int inx)
{
shu[inx][rt].ls = shu[inx][rt<<1].ls;
shu[inx][rt].rs = shu[inx][rt<<1|1].rs;
if(shu[inx][rt<<1].ls==(shu[inx][rt<<1].r - shu[inx][rt<<1].l + 1))
{
shu[inx][rt].ls += shu[inx][rt<<1|1].ls;
}
if(shu[inx][rt<<1|1].rs==(shu[inx][rt<<1|1].r - shu[inx][rt<<1|1].l + 1))
{
shu[inx][rt].rs += shu[inx][rt<<1].rs;
}
shu[inx][rt].sum = max(max(shu[inx][rt<<1].sum,shu[inx][rt<<1|1].sum),shu[inx][rt<<1].rs+shu[inx][rt<<1|1].ls);
}
void pushdown(int rt,int inx)
{
if(shu[inx][rt].lazy == 1)
{
shu[inx][rt<<1].ls = shu[inx][rt<<1].rs = shu[inx][rt<<1].sum = (shu[inx][rt<<1].r - shu[inx][rt<<1].l + 1);
shu[inx][rt<<1|1].ls = shu[inx][rt<<1|1].rs = shu[inx][rt<<1|1].sum = (shu[inx][rt<<1|1].r - shu[inx][rt<<1|1].l + 1);
shu[inx][rt<<1].lazy = shu[inx][rt].lazy;
shu[inx][rt<<1|1].lazy = shu[inx][rt].lazy;
shu[inx][rt].lazy = 0;
}
else if(shu[inx][rt].lazy == 2)
{
shu[inx][rt<<1].ls = shu[inx][rt<<1].rs = shu[inx][rt<<1].sum = 0;
shu[inx][rt<<1|1].ls = shu[inx][rt<<1|1].rs = shu[inx][rt<<1|1].sum = 0;
shu[inx][rt<<1].lazy = shu[inx][rt].lazy;
shu[inx][rt<<1|1].lazy = shu[inx][rt].lazy;
shu[inx][rt].lazy = 0;
}
}
void build(int rt,int l,int r,int inx)
{
shu[inx][rt].l = l,shu[inx][rt].r = r;
shu[inx][rt].lazy = 0;
if(l==r)
{
shu[inx][rt].ls = shu[inx][rt].rs = shu[inx][rt].sum = 1;
return;
}
int mid = (l+r)>>1;
build(rt<<1,l,mid,inx);
build(rt<<1|1,mid+1,r,inx);
pushup(rt,inx);
}
void update(int rt,int l,int r,int val,int inx)
{
int L = shu[inx][rt].l , R = shu[inx][rt].r;
if(l<=L&&R<=r)
{
if(val)
{
shu[inx][rt].ls = shu[inx][rt].rs = shu[inx][rt].sum = R-L+1;
shu[inx][rt].lazy = 1;
}
else
{
shu[inx][rt].ls = shu[inx][rt].rs = shu[inx][rt].sum = 0;
shu[inx][rt].lazy = 2;
}
}
else
{
pushdown(rt,inx);
int mid = (L+R)>>1;
if(l<=mid) update(rt<<1,l,r,val,inx);
if(mid<r) update(rt<<1|1,l,r,val,inx);
pushup(rt,inx);
}
}
int Find(int rt,int val,int inx)
{
if(shu[inx][rt].ls == val) return shu[inx][rt].l; //当前区间最左边可以吗
if(shu[inx][rt].sum>=val) //当前区间可以吗
{
pushdown(rt,inx); //下传
if(shu[inx][rt<<1].sum>=val) return Find(rt<<1,val,inx); //当前区间左儿子可以吗
if(shu[inx][rt<<1].rs+shu[inx][rt<<1|1].ls >=val) return shu[inx][rt<<1].r - shu[inx][rt<<1].rs+1; // 当前区间分开的中间可以吗
if(shu[inx][rt<<1|1].sum>=val) return Find(rt<<1|1,val,inx); // 当前区间右儿子可以吗
}
return 0;
}
int main()
{
int t;
scanf("%d",&t);
int kk = 1;
while(t--)
{
int n,m;
scanf("%d%d",&n,&m);
memset(shu,0,sizeof(shu));
build(1,1,n,0); // 0代表ds树
build(1,1,n,1); // 1代表ns树
printf("Case %d:\n",kk++);
char s1[10];
for(int i=0; i<m; i++)
{
scanf("%s",s1);
if(s1[0]=='D')
{
int x;
scanf("%d",&x);
int ans = Find(1,x,0);
if(ans == 0 ) printf("fly with yourself\n");
else
{
update(1,ans,ans+x-1,0,0);
printf("%d,let's fly\n",ans);
}
}
else if(s1[0]=='N')
{
int x;
scanf("%d",&x);
int ans = Find(1,x,0);
//printf("DS: %d\n",ans);
if(ans == 0)
{
int res = Find(1,x,1);
//printf("NS: %d\n",res);
if(res == 0)
{
printf("wait for me\n");
}
else
{
update(1,res,res+x-1,0,1);
update(1,res,res+x-1,0,0);
printf("%d,don't put my gezi\n",res);
}
}
else
{
update(1,ans,ans+x-1,0,0);
update(1,ans,ans+x-1,0,1);
printf("%d,don't put my gezi\n",ans);
}
}
else if(s1[0]=='S')
{
int l,r;
scanf("%d%d",&l,&r);
update(1,l,r,1,0);
update(1,l,r,1,1);
printf("I am the hope of chinese chengxuyuan!!\n");
}
}
}
}
如果觉得有什么疑惑或者博主代码有什么问题,可以通过关于我,加我QQ联系 ,感谢。