线段树二分
用2个线段树分别维护男生预约的时间段和女生预约的时间段。
线段树里面保存的是最大连续子段和,空闲时间为1,预约了的话就是0。
当男生来预约的时候,只需要修改男生的线段树即可。 而当女生来预约的时候若在男生的线段树里面找不到空闲时间再去女生线段树里面查找,若找到就修改男生和女生2个线段树(因为女生可以无视基友)。
每次查询修改时候进行区间下放。
查询的时候分成3种情况,首先如果调用查询函数代表一定有那么多空闲时间。
1.在左区间
2.左边区间和右边区间合并得来的答案,这种情况直接返回这个区间的左端点即可。
3.在右区间
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 2e6 + 10;
struct tnode
{
int l, r;
int lazy;
int lmx, rmx, ans;//最大子段和
tnode friend operator +(tnode a, tnode b)
{
tnode res;
res.l = a.l;
res.r = b.r;
res.lazy=-1;
res.lmx = a.lmx + (a.lmx == (a.r - a.l + 1) ? b.lmx : 0);
res.rmx = b.rmx + (b.rmx == (b.r - b.l + 1) ? a.rmx : 0);
res.ans = max(max(a.ans, b.ans), max(res.lmx, res.rmx));
res.ans=max(res.ans,a.rmx+b.lmx);
return res;
}
};
int n, m;
struct segment_tree
{
#define lch (root<<1)
#define rch (root<<1|1)
#define mid (t[root].l+t[root].r>>1)
tnode t[MAXN<<2];
void pushup(int root)
{
t[root] = t[lch] + t[rch];
}
void pushdown(int root)
{
if (t[root].lazy == -1)return;
t[lch].lazy = t[root].lazy;
t[lch].lmx = t[lch].rmx = t[lch].ans =(t[lch].r - t[lch].l + 1) * t[root].lazy;
t[rch].lazy = t[root].lazy;
t[rch].lmx = t[rch].rmx = t[rch].ans =(t[rch].r - t[rch].l + 1) * t[root].lazy;
t[root].lazy = -1;
}
void build(int root, int l, int r)
{
t[root].l = l;
t[root].r = r;
t[root].lazy = -1;
if (l == r) {
t[root].lmx = t[root].rmx = t[root].ans =1;
return;
}
build(lch, l, mid);
build(rch, mid + 1, r);
pushup(root);
}
void fugai(int root, int ql, int qr, int v)
{
if (t[root].l > qr || t[root].r < ql)return;
if (t[root].l >= ql && t[root].r <= qr)
{
t[root].lazy = v;
t[root].lmx = t[root].rmx = t[root].ans = (t[root].r - t[root].l + 1) * v;
return;
}
pushdown(root);
fugai(lch, ql, qr, v);
fugai(rch, ql, qr, v);
pushup(root);
}
void ask(int root,int len,int &res)
{
if(t[root].l==t[root].r){res=min(t[root].l,res);return;}
pushdown(root);
if(t[lch].ans>=len)ask(lch,len,res);
else if(t[lch].rmx+t[rch].lmx>=len)res=min(res,(mid-t[lch].rmx+1));
else if(t[rch].ans>=len)ask(rch,len,res);
pushup(root);
return;
}
int ask(int root,int len)
{
if(t[root].l==t[root].r)return t[root].l;
pushdown(root);
if(t[lch].ans>=len)return ask(lch,len);
else if(t[lch].rmx+t[rch].lmx>=len)return mid-t[lch].rmx+1;
else return ask(rch,len);
}
#undef lch
#undef rch
#undef mid
}man,weman;
int main()
{
int T;
scanf("%d", &T);
for (int ci = 1; ci <= T; ci++) {
scanf("%d%d", &n, &m);
man.build(1, 1, n);
weman.build(1, 1, n);
printf("Case %d:\n", ci);
for (int i = 1; i <= m; i++) {
char s[33];
int x,y;
scanf("%s%d", s, &x);
if (s[0] == 'D') {
if (man.t[1].ans >= x) {
int t=man.ask(1,x);
man.fugai(1,t,t+x-1,0);
printf("%d,let's fly\n", t);
}
else {
printf("fly with yourself\n");
}
}
else if (s[0] == 'N') {
if (man.t[1].ans >= x) {
int t=man.ask(1,x);
man.fugai(1,t,t+x-1,0);
weman.fugai(1,t,t+x-1,0);
printf("%d,don't put my gezi\n", t);
}
else if (weman.t[1].ans >= x) {
int t=weman.ask(1,x);
weman.fugai(1,t,t+x-1,0);
man.fugai(1,t,t+x-1,0);
printf("%d,don't put my gezi\n", t);
}
else {
printf("wait for me\n");
}
}
else {
scanf("%d", &y);
man.fugai(1,x,y,1);
weman.fugai(1,x,y,1);
printf("I am the hope of chinese chengxuyuan!!\n");
}
}
}
return 0;
}