约会安排(线段树区间和并)

这篇博客讲述了作者在解决区间合并问题时遇到的挑战,通过两天的努力深化了对线段树、懒标记操作的理解。文章指出,线段树的代码通常复杂冗长,并且在处理小明和女神两个不同操作时,需要确保女神的优先级高于小明,同时正确处理两者间的时间占用问题。

传送门

差点把自己给做吐了

区间合并的题目,虽然自己做着很难受,做了两天,不过又加深了对区间和并以及懒标记以及相关操作的认识。

有一说一,线段树的代码真是又臭又长

  • 设置了两个懒标记,一个是小明的,一个是女神的
  • 女神的优先级要高于小明
  • 当只对小明进行操作时,与女神没有关系。而当对女神进行操作时,小明维护的各种信息也要进行相应的操作,说白了也就是时间被占用。
  • 当初设置的两个懒标记的姿势不太正确,冲突了
#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;

const int N = 100010;
struct Node{
    int l, r, dlmax, drmax, dsmax, nlmax, nrmax, nsmax;
    int dtag, ntag;
}node[N << 2];

void pushup(int root, int id){
	if(id == 0){
		if(node[root << 1].dsmax == node[root << 1].r - node[root << 1].l + 1)
			node[root].dlmax = node[root << 1].dsmax + node[root << 1 | 1].dlmax;
		else
			node[root].dlmax = node[root << 1].dlmax;
		if(node[root << 1 | 1].dsmax == node[root << 1 | 1].r - node[root << 1].r)
			node[root].drmax = node[root << 1 | 1].dsmax + node[root << 1].drmax;
		else
			node[root].drmax = node[root << 1 | 1].drmax;
		node[root].dsmax = max(max(node[root << 1].dsmax, node[root << 1 | 1].dsmax), node[root << 1].drmax + node[root << 1 | 1].dlmax);
	}else{
		if(node[root << 1].dsmax == node[root << 1].r - node[root << 1].l + 1)
			node[root].dlmax = node[root << 1].dsmax + node[root << 1 | 1].dlmax;
		else
			node[root].dlmax = node[root << 1].dlmax;
		if(node[root << 1 | 1].dsmax == node[root << 1 | 1].r - node[root << 1].r)
			node[root].drmax = node[root << 1 | 1].dsmax + node[root << 1].drmax;
		else
			node[root].drmax = node[root << 1 | 1].drmax;
		node[root].dsmax = max(max(node[root << 1].dsmax, node[root << 1 | 1].dsmax), node[root << 1].drmax + node[root << 1 | 1].dlmax);

		if(node[root << 1].nsmax == node[root << 1].r - node[root << 1].l + 1)
			node[root].nlmax = node[root << 1].nsmax + node[root << 1 | 1].nlmax;
		else
			node[root].nlmax = node[root << 1].nlmax;
		if(node[root << 1 | 1].nsmax == node[root << 1 | 1].r - node[root << 1].r)
			node[root].nrmax = node[root << 1 | 1].nsmax + node[root << 1].nrmax;
		else
			node[root].nrmax = node[root << 1 | 1].nrmax;
		node[root].nsmax = max(max(node[root << 1].nsmax, node[root << 1 | 1].nsmax), node[root << 1].nrmax + node[root << 1 | 1].nlmax);
	}
}

void build(int root, int l, int r){
    node[root].l = l;
    node[root].r = r;
    node[root].dtag = -1;
    node[root].ntag = -1;
    node[root].dlmax = node[root].drmax = node[root].dsmax = node[root].nlmax = node[root].nrmax = node[root].nsmax = r - l + 1;
    if(l == r){
        return;
    }
    int mid = l + r >> 1;
    build(root << 1, l, mid);
    build(root << 1 | 1, mid + 1, r);
    //pushup)
}

void pushdown(int root){
	if(node[root].dtag != -1){
		node[root << 1].dtag = node[root].dtag;
		node[root << 1 | 1].dtag = node[root].dtag;
		node[root << 1].dlmax = node[root << 1].drmax = node[root << 1].dsmax = node[root].dtag? 0 : node[root << 1].r - node[root << 1].l + 1;
		node[root << 1 | 1].dlmax = node[root << 1 | 1].drmax = node[root << 1 | 1].dsmax = node[root].dtag? 0 : node[root << 1 | 1].r - node[root << 1].r; 
		node[root].dtag = -1;
	}
	if(node[root].ntag != -1){
		node[root << 1].ntag = node[root].ntag;
		node[root << 1 | 1].ntag = node[root].ntag;
		node[root << 1].nlmax = node[root << 1].nrmax = node[root << 1].nsmax = node[root].ntag ? 0 : node[root << 1].r - node[root << 1].l + 1;
		node[root << 1 | 1].nlmax = node[root << 1 | 1].nrmax = node[root << 1 | 1].nsmax = node[root].ntag ? 0 : node[root << 1 | 1].r - node[root << 1].r; 
		node[root].ntag = -1;
	}
}
void change(int root, int l, int r, int id, int value){
	if(node[root].l >= l && node[root].r <= r){
		if(id == 0){
			node[root].dlmax = node[root].drmax = node[root].dsmax = value? 0:node[root].r - node[root].l + 1;
			node[root].dtag = value;
		}
		else{
			node[root].nlmax = node[root].nrmax = node[root].nsmax = value? 0:node[root].r - node[root].l + 1;
			node[root].ntag = value;
		}
		return;	
	}
	pushdown(root);
	int mid = node[root].l + node[root].r >> 1;
	if(l <= mid)
		change(root << 1, l, r, id, value);
	if(r > mid)
		change(root << 1 | 1, l, r, id, value);
	pushup(root, id);
}
int query(int root, int len, int id){
	if(node[root].l == node[root].r)
		return node[root].l;
	pushdown(root);
	if(id == 0){
		if(node[root << 1].dsmax >= len)
			return query(root << 1, len, id);
		else if(node[root << 1].drmax + node[root << 1 | 1].dlmax >= len)
			return node[root << 1].r - node[root << 1].drmax + 1;
		else
			return query(root << 1 | 1, len, id); 
	}else{
		if(node[root << 1].nsmax >= len)
			return query(root << 1, len, id);
		else if(node[root << 1].nrmax + node[root << 1 | 1].nlmax >= len)
			return node[root << 1].r - node[root << 1].nrmax + 1;
		else
			return query(root << 1 | 1, len, id); 
	}
}
		
int main(){
    int t, kase = 0;
    cin >> t;
    while(t --){
        int time, n;
        scanf("%d%d", &time, &n);
        build(1, 1, time);
        printf("Case %d:\n", ++ kase);
        while(n --){
            char name[10];
            scanf("%s", name);
            if(name[0] == 'D'){
                int len;
                scanf("%d", &len);
                if(node[1].dsmax >= len){
                    int t = query(1, len, 0);
                    printf("%d,let's fly\n", t);
                    change(1, t, t + len - 1, 0, 1);
                }else{
                    printf("fly with yourself\n");
                }
            }else if(name[0] == 'N'){
                int len;
                scanf("%d", &len);
                if(node[1].dsmax >= len){  	
                    int t = query(1, len, 0);
                    printf("%d,don't put my gezi\n", t);
                    change(1, t, t + len - 1, 0, 1);
                    change(1, t, t + len - 1, 1, 1);
                }else if(node[1].nsmax >= len){
                    int t = query(1, len, 1);
                    printf("%d,don't put my gezi\n", t);
                    change(1, t, t + len - 1, 0, 1);
                    change(1, t, t + len - 1, 1, 1);
                }else{
                    printf("wait for me\n");
                }
            }else{
                int x, y;
                scanf("%d%d", &x, &y);	
               	change(1, x, y, 0, 0);
               	change(1, x, y, 1, 0);
                printf("I am the hope of chinese chengxuyuan!!\n");
            }
        }
        
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值