题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4553
算是poj3667的加强版,建立两颗线段树,一个是DS区间,另一个是NS区间。那么根据题意,如果是DS的请求,那么首先查找DS的区间,如果有满足的区间就更新DS区间,NS的区间不需要更新。如果是NS的请求,首先看DS区间是否有满足的区间,否则查找NS区间,如果有就同时更新DS区间和NS区间。那么可以归纳为,只要是NS的请求,就同时更新两颗线段树,否则只更新DS的线段树。
注意输出要从Output中复制,不然会wa道底,还有就是Up函数中的if顺序不能变;
这两道题写了一天,不过值了,当然如果不是因为有学长的博客在,我一天根本写不出来,学长毕竟是学长;
#include<iostream> #include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define INF 0xfffffff #define N 110050 #define Lson r<<1 #define Rson r<<1|1 struct SegmentTree { int L, R; bool ns, ds, study; ///0代表 int lsum[2], rsum[2], sum[2]; ///0是屌丝,1女神; ///lsum区间左边(从L开始)连续最大不被覆盖的值 ///rsum区间右边(到R介绍)连续最大不被覆盖的值 ///sum整个区间连续最大不被覆盖的值 int Mid() { return (L+R)>>1;} int len() { return R-L+1; } void clearPlan(bool x)///清空; { if(x) { lsum[0] = lsum[1] = len(); rsum[0] = rsum[1] = len(); sum[0] = sum[1] = len(); ns = ds = false; study = true; } } void NS(bool x)///女神; { if(x) { lsum[0] = lsum[1] = 0; rsum[0] = rsum[1] = 0; sum[0] = sum[1] = 0; ns = true; ds = false; } } void DS(bool x)///屌丝; { if(x) { lsum[0] = rsum[0] = sum[0] = 0; ds = true; } } } a[N<<2]; void Build(int r, int L, int R) { a[r].L = L, a[r].R = R; a[r].clearPlan(true);///清空 ; a[r].ns = a[r].ds = a[r].study = false; if(L == R)return ; Build(Lson, L, a[r].Mid()); Build(Rson, a[r].Mid()+1, R); } void Up(int r, int who) { if(a[r].L != a[r].R) { a[r].lsum[who] = a[Lson].lsum[who]; a[r].rsum[who] = a[Rson].rsum[who]; if(a[Lson].lsum[who] == a[Lson].len()) a[r].lsum[who] += a[Rson].lsum[who]; if(a[Rson].rsum[who] == a[Rson].len()) a[r].rsum[who] += a[Lson].rsum[who]; a[r].sum[who] = max(a[Lson].rsum[who] + a[Rson].lsum[who], max(a[Lson].sum[who], a[Rson].sum[who])); } } void Down(int r)///这个顺序不能反 { if(a[r].study) { a[Lson].clearPlan(true); a[Rson].clearPlan(true); a[r].study = false; } if(a[r].ns) { a[Lson].NS(true); a[Rson].NS(true); a[r].ns = a[r].ds = false; } if(a[r].ds) { a[Lson].DS(true); a[Rson].DS(true); a[r].ds = false; } } void Update(int r, int L, int R, int flag) { if(a[r].L == L && a[r].R == R) { if(flag == 3) a[r].DS(true); if(flag == 2) a[r].NS(true); if(flag == 1) a[r].clearPlan(true); return; } Down(r); if( R <= a[r].Mid()) Update(Lson, L, R, flag); else if( L > a[r].Mid()) Update(Rson, L, R, flag); else { Update(Lson, L, a[r].Mid(), flag); Update(Rson, a[r].Mid()+1, R, flag); } Up(r, 0); Up(r, 1); } int Query(int r, int num, int who) { Down(r); if(a[r].sum[who] < num) return 0; if(a[r].lsum[who] >= num) return a[r].L; if(a[Lson].sum[who] >= num) return Query(Lson, num, who); if(a[Lson].rsum[who]+a[Rson].lsum[who] >= num) return a[Lson].R - a[Lson].rsum[who] + 1; return Query(Rson, num, who); } int main() { int n, m, T, t = 1, R, L, time; scanf("%d", &T); while(T--) { scanf("%d %d", &n, &m); Build(1, 1, n); printf("Case %d:\n", t++); while(m--) { char s[1100]; scanf("%s", s); if(s[0] == ‘D‘) { scanf("%d", &time); L = Query(1, time, 0);///屌丝是0; if( !L )printf("fly with yourself\n"); else { Update(1, L, L+time-1, 3); printf("%d,let‘s fly\n", L); } } else if(s[0] == ‘N‘) { scanf("%d", &time); L = Query(1, time, 0);///先在屌丝时间里找;当在屌丝时间里没时间时在女神时间里找; if( !L ) L = Query(1, time, 1);///女神是1; if( !L )printf("wait for me\n"); else { Update(1, L, L+time-1, 2); printf("%d,don‘t put my gezi\n", L); } } else { scanf("%d %d", &L, &R); Update(1, L, R, 1); printf("I am the hope of chinese chengxuyuan!!\n"); } } } return 0; }
时间: 2024-10-27 13:06:10