HDU

来源:互联网 发布:淘宝好听的用户名大全 编辑:程序博客网 时间:2024/05/29 09:49

题目链接: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|1using 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;}


原创粉丝点击