题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4553
题目思路:本题就是一个线段树的区间合并,定义三个懒惰标记:屌丝标记,女神标记,学习标记,三个的优先级为学习 > 女神 > 屌丝,更新时按照这个优先级更新即可,查询时,屌丝就直接查看屌丝区间是否有空闲时间,女神优先看屌丝区间和女神区间是否有空闲时间,否则就覆盖已有的屌丝区间,学习就是将屌丝区间和女神区间内的所有值清空,具体操作代码里都有解释。
AC代码如下:
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define FIN freopen("in.txt","r",stdin)
#define fuck(x) cout<<'['<<x<<']'<<endl
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
typedef long long LL;
typedef pair<int, int>pii;
const int MX = 1e5 + 10;
struct node {
int n, d, s;//n代表女神的懒惰标记,d代表屌丝的懒惰标记,s代表学习的懒惰标记;
int nls, nrs, nms;//分别代表女神的左连续最长区间,右连续最长区间和总连续最长区间;
int dls, drs, dms;//分别代表屌丝的左连续最长区间,右连续最长区间和总连续最长区间;
} a[MX << 2];//所储存的是可用的空闲时间是多少,方便查询;
void update_d(int rt) {
a[rt].d = 1;
a[rt].dls = a[rt].drs = a[rt].dms = 0;
}
void update_n(int rt) {
a[rt].n = 1;
a[rt].d = 0;
a[rt].nls = a[rt].nrs = a[rt].nms = 0;
a[rt].dls = a[rt].drs = a[rt].dms = 0;//女神的优先级高于屌丝,所以更新女神时也要把屌丝的区间长度也更新;
}
void update_s(int l, int r, int rt) {
a[rt].s = 1;
a[rt].d = a[rt].n = 0;
a[rt].dls = a[rt].drs = a[rt].dms = r - l + 1;
a[rt].nls = a[rt].nrs = a[rt].nms = r - l + 1;
//学习的优先级最高,所以更新时需将整个区间内女神和屌丝的所有标记都更新掉;
}
void Push_Up(int l, int r, int rt) {
int m = (l + r) >> 1;
a[rt].dms = max(a[rt << 1].dms, max(a[rt << 1 | 1].dms, a[rt << 1].drs + a[rt << 1 | 1].dls));
//父节点的总连续区间长度 = MAX(左儿子的左连续最长区间,右儿子的右连续最长区间,左儿子的右连续区间 + 右儿子的左连续最长区间);
a[rt].dls = a[rt << 1].dls;
a[rt].drs = a[rt << 1 | 1].drs;
if(a[rt].dls == m - l + 1)//如果左儿子的左连续最长区间是满的,那么父节点的左连续最长区间要加上右儿子的左连续最长区间;
a[rt].dls += a[rt << 1 | 1].dls;
if(a[rt].drs == r - m)//右儿子同理;
a[rt].drs += a[rt << 1].drs;
a[rt].nms = max(a[rt << 1].nms, max(a[rt << 1 | 1].nms, a[rt << 1].nrs + a[rt << 1 | 1].nls));
a[rt].nls = a[rt << 1].nls;
a[rt].nrs = a[rt << 1 | 1].nrs;
if(a[rt].nls == m - l + 1)
a[rt].nls += a[rt << 1 | 1].nls;
if(a[rt].nrs == r - m)
a[rt].nrs += a[rt << 1].nrs;
}
void Push_Down(int l, int r, int rt) {
int m = (l + r) >> 1;
if(a[rt].s) {
update_s(lson);
update_s(rson);
a[rt].s = 0;
}//更新时学习的优先级最高,优先更新;
if(a[rt].n) {
update_n(rt << 1);
update_n(rt << 1 | 1);
a[rt].n = 0;
}//女神优先级第二,接着更新女神;
if(a[rt].d) {
update_d(rt << 1);
update_d(rt << 1 | 1);
a[rt].d = 0;
}//最后更新屌丝;
}
void study(int L, int R, int l, int r, int rt) {
if(L <= l && r <= R) {
update_s(l, r, rt);
return;
}
int m = (l + r) >> 1;
Push_Down(l, r, rt);
if(L <= m) study(L,R,lson);
if(R > m) study(L,R,rson);
Push_Up(l, r, rt);
}
void Update(int L, int R, int c, int l, int r, int rt) {
if(L <= l && r <= R) {
if(c == 0)//0代表屌丝;
update_d(rt);
else
update_n(rt);
return;
}
int m = (l + r) >> 1;
Push_Down(l, r, rt);
if(L <= m) Update(L,R,c,lson);
if(R > m) Update(L,R,c,rson);
Push_Up(l, r, rt);
}
int Query(int w, int f, int l, int r, int rt) {
if(l == r) return l;
Push_Down(l, r, rt);
int m = (l + r) >> 1;
if(f == 0) {
if(a[rt << 1].dms >= w)
return Query(w, f, lson);//如果左儿子的总连续区间大于所要的长度,则往左儿子更新;
else if(a[rt << 1].drs + a[rt << 1 | 1].dls >= w)
return m - a[rt << 1].drs + 1;//如果是合并后的区间大于所要长度,则直接返回;
else
return Query(w, f, rson);//如果右儿子的总连续区间大于所要的长度,则往右儿子更新;
} else {//女神的查询同理;
if(a[rt << 1].nms >= w)
return Query(w, f, lson);
else if(a[rt << 1].nrs + a[rt << 1 | 1].nls >= w)
return m - a[rt << 1].nrs + 1;
else
return Query(w, f, rson);
}
}
int T;
int n, m;
int main() {
// FIN;
scanf("%d", &T);
int cas = 1;
while(T--) {
scanf("%d%d", &n, &m);
study(1, n, 1, n, 1);
printf("Case %d:\n", cas++);
while(m--) {
char op[10];
int x, y;
scanf("%s", op);
if(op[0] == 'D') {
scanf("%d", &x);
if(a[1].dms < x)//如果可用的时间不够,直接输出;
puts("fly with yourself");
else {
int ans = Query(x, 0, 1, n, 1);
Update(ans, ans + x - 1, 0, 1, n, 1);
printf("%d,let's fly\n", ans);
}
} else if(op[0] == 'N') {
scanf("%d", &x);
if(a[1].dms < x) {//如果屌丝区间剩余的时间不够,则查看女神区间;
if(a[1].nms < x)
puts("wait for me");
else {
int ans = Query(x, 1, 1, n, 1);
Update(ans, ans + x - 1, 1, 1, n, 1);
printf("%d,don't put my gezi\n", ans);
}
}
else{//否则直接占用屌丝区间的时间;
int ans = Query(x,0,1,n,1);
Update(ans,ans + x - 1,1,1,n,1);
printf("%d,don't put my gezi\n", ans);
}
} else {
scanf("%d%d", &x, &y);
study(x, y, 1, n, 1);
puts("I am the hope of chinese chengxuyuan!!");
}
}
}
return 0;
}