HDU4553:约会安排(线段树)(第三部分 区间合并)
来源:互联网 发布:office苹果mac版 编辑:程序博客网 时间:2024/05/06 05:25
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4553
题目大意:查找是否有连续的空余时间
他的操作有三个 :
ds x 查找屌丝的时间有连续的x长度的空余时间
ns x 为女神安排时间,先查找屌丝时间是否有空余,没有的话无视屌丝,直接判断女神时间是否有连续x长的空余时间
stduy a b 清空a到b区间的事情
思路:
一:存线段树数据的数组要有九个变量。
struct node{ int d,n,s;//d屌丝延迟标记 n女神延迟标记 s学习延迟标记 int ls,rs,ms;//屌丝的左 右 区间最大的连续空时间的长 int nsl,nsr,nsm;//女神的左 右 区间最大的连续空时间的长} a[L<<2];二:关于pushdown函数
void pushdown(int l,int r,int rt)//延迟标记的向下传递{ int m = (l+r)>>1; if(a[rt].s) { xuexi(lson); xuexi(rson); a[rt].s = 0; } if(a[rt].d) { diaosi(lson); diaosi(rson); a[rt].d = 0; } if(a[rt].n) { nvshen(lson); nvshen(rson); a[rt].n = 0; }}
pushdown函数是将延迟标记的信息向下传递
而延迟标记有三种 学习,屌丝,女神,注意学习标记优先级最大
分别对每种标记有如下的操作:
void diaosi(int l,int r,int rt)//屌丝的延迟标记处理{ a[rt].d = 1; a[rt].ls = a[rt].rs = a[rt].ms = 0;}void nvshen(int l,int r,int rt)//女神的延迟标记处理 不仅要将屌丝时间占据 女神时间也要占据{ a[rt].n = 1; a[rt].d = 0; a[rt].ls = a[rt].rs = a[rt].ms = 0; a[rt].nsl = a[rt].nsr = a[rt].nsm = 0;}void xuexi(int l,int r,int rt)//学习延迟标记 全部清理成空的时间{ a[rt].s = 1; a[rt].d = a[rt].n = 0; a[rt].ls = a[rt].rs = a[rt].ms = r-l+1; a[rt].nsl = a[rt].nsr = a[rt].nsm = r-l+1;}
这里需要特别注意的是女神标记的处理,他不仅要对自己女神时间进行处理,同时也要对相应的屌丝时间进行处理
三:关于pushup函数
void pushup(int l,int r,int rt)//屌丝和女神区间的合并{ int mid = (l+r)>>1; int m=r-l+1; a[rt].ms = max(a[rt<<1].ms,a[rt<<1|1].ms); a[rt].ms = max(a[rt].ms,a[rt<<1].rs+a[rt<<1|1].ls); a[rt].ls = a[rt<<1].ls; a[rt].rs = a[rt<<1|1].rs; if(a[rt<<1].ls == m-(m>>1)) a[rt].ls+=a[rt<<1|1].ls; if(a[rt<<1|1].rs == (m>>1)) a[rt].rs+= a[rt<<1].rs; a[rt].nsm = max(a[rt<<1].nsm,a[rt<<1|1].nsm); a[rt].nsm = max(a[rt].nsm,a[rt<<1].nsr+a[rt<<1|1].nsl); a[rt].nsl = a[rt<<1].nsl; a[rt].nsr = a[rt<<1|1].nsr; if(a[rt<<1].nsl == m-(m>>1)) a[rt].nsl+=a[rt<<1|1].nsl; if(a[rt<<1|1].nsr ==(m>>1)) a[rt].nsr+= a[rt<<1].nsr;}
这个就是一个典型的区间合并 女神和屌丝同样处理
四:查找连续长度为t的连续区间 注意一个是屌丝查询 一个是女神查询 分开处理
int query(int flag,int t,int l,int r,int rt){ if(l==r) return l; int m = (l+r)>>1; pushdown(l,r,rt); if(!flag)//屌丝时间查询 { if(a[rt<<1].ms>=t)//左子树有时间 return query(flag,t,lson); else if(a[rt<<1].rs+a[rt<<1|1].ls>=t)//左子树部分加右子树部分 return m-a[rt<<1].rs+1; else//右子树有时间 return query(flag,t,rson); } else//女神时间查询 直接无视屌丝 { if(a[rt<<1].nsm>=t) return query(flag,t,lson); else if(a[rt<<1].nsr+a[rt<<1|1].nsl>=t) return m-a[rt<<1].nsr+1; else return query(flag,t,rson); }}
因为要求时间尽可能早,所有从左子树开始查询,然后左部分加右部分,最后是右子树
五:对区间进行处理 将其覆盖成屌丝时间或者女神时间
void insert(int flag,int L,int R,int l,int r,int rt){ if(l == L && r == R) { if(!flag)//将那段时间设为屌丝时间 diaosi(l,r,rt); else//将那段时间设为女神时间 nvshen(l,r,rt); return ; } int m = (l+r)>>1; pushdown(l,r,rt); if(R<=m) insert(flag,L,R,lson); else if(L>m) insert(flag,L,R,rson); else { insert(flag,L,m,lson); insert(flag,m+1,R,rson); } pushup(l,r,rt);}
接下里是完整的ac代码
#include <stdio.h>#include <string.h>#include <algorithm>using namespace std;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1const int L = 100000+10;struct node{ int d,n,s;//d屌丝延迟标记 n女神延迟标记 s学习延迟标记 int ls,rs,ms;//屌丝的左 右 区间最大的连续空时间的长 int nsl,nsr,nsm;//女神的左 右 区间最大的连续空时间的长} a[L<<2];void diaosi(int l,int r,int rt)//屌丝的延迟标记处理{ a[rt].d = 1; a[rt].ls = a[rt].rs = a[rt].ms = 0;}void nvshen(int l,int r,int rt)//女神的延迟标记处理 不仅要将屌丝时间占据 女神时间也要占据{ a[rt].n = 1; a[rt].d = 0; a[rt].ls = a[rt].rs = a[rt].ms = 0; a[rt].nsl = a[rt].nsr = a[rt].nsm = 0;}void xuexi(int l,int r,int rt)//学习延迟标记 全部清理成空的时间{ a[rt].s = 1; a[rt].d = a[rt].n = 0; a[rt].ls = a[rt].rs = a[rt].ms = r-l+1; a[rt].nsl = a[rt].nsr = a[rt].nsm = r-l+1;}void pushup(int l,int r,int rt)//屌丝和女神区间的合并{ int mid = (l+r)>>1; int m=r-l+1; a[rt].ms = max(a[rt<<1].ms,a[rt<<1|1].ms); a[rt].ms = max(a[rt].ms,a[rt<<1].rs+a[rt<<1|1].ls); a[rt].ls = a[rt<<1].ls; a[rt].rs = a[rt<<1|1].rs; if(a[rt<<1].ls == m-(m>>1)) a[rt].ls+=a[rt<<1|1].ls; if(a[rt<<1|1].rs == (m>>1)) a[rt].rs+= a[rt<<1].rs; a[rt].nsm = max(a[rt<<1].nsm,a[rt<<1|1].nsm); a[rt].nsm = max(a[rt].nsm,a[rt<<1].nsr+a[rt<<1|1].nsl); a[rt].nsl = a[rt<<1].nsl; a[rt].nsr = a[rt<<1|1].nsr; if(a[rt<<1].nsl == m-(m>>1)) a[rt].nsl+=a[rt<<1|1].nsl; if(a[rt<<1|1].nsr ==(m>>1)) a[rt].nsr+= a[rt<<1].nsr;}void pushdown(int l,int r,int rt)//延迟标记的向下传递{ int m = (l+r)>>1; if(a[rt].s) { xuexi(lson); xuexi(rson); a[rt].s = 0; } if(a[rt].d) { diaosi(lson); diaosi(rson); a[rt].d = 0; } if(a[rt].n) { nvshen(lson); nvshen(rson); a[rt].n = 0; }}void study(int L,int R,int l,int r,int rt){ if(L == l && R == r) { xuexi(l,r,rt); return ; } int m = (l+r)>>1; pushdown(l,r,rt); if(R<=m) study(L,R,lson); else if(L>m) study(L,R,rson); else { study(L,m,lson); study(m+1,R,rson); } pushup(l,r,rt);}void insert(int flag,int L,int R,int l,int r,int rt){ if(l == L && r == R) { if(!flag)//将那段时间设为屌丝时间 diaosi(l,r,rt); else//将那段时间设为女神时间 nvshen(l,r,rt); return ; } int m = (l+r)>>1; pushdown(l,r,rt); if(R<=m) insert(flag,L,R,lson); else if(L>m) insert(flag,L,R,rson); else { insert(flag,L,m,lson); insert(flag,m+1,R,rson); } pushup(l,r,rt);}int query(int flag,int t,int l,int r,int rt){ if(l==r) return l; int m = (l+r)>>1; pushdown(l,r,rt); if(!flag)//屌丝时间查询 { if(a[rt<<1].ms>=t)//左子树有时间 return query(flag,t,lson); else if(a[rt<<1].rs+a[rt<<1|1].ls>=t)//左子树部分加右子树部分 return m-a[rt<<1].rs+1; else//右子树有时间 return query(flag,t,rson); } else//女神时间查询 直接无视屌丝 { if(a[rt<<1].nsm>=t) return query(flag,t,lson); else if(a[rt<<1].nsr+a[rt<<1|1].nsl>=t) return m-a[rt<<1].nsr+1; else return query(flag,t,rson); }}int main(){ int t,i,x,y,ans,cas = 1,n,m; char str[20]; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); printf("Case %d:\n",cas++); study(1,n,1,n,1); //区间1~n全部清零 while(m--) { scanf("%s",str); if(str[0] == 'D') { scanf("%d",&x); if(a[1].ms<x)//线段树最大的区间都小于给定的时间就不用找了 printf("fly with yourself\n"); else { ans = query(0,x,1,n,1);//查询到位置 insert(0,ans,ans+x-1,1,n,1); printf("%d,let's fly\n",ans); } } else if(str[0] == 'N') { scanf("%d",&x); if(a[1].ms<x)//屌丝时间找不到空余时间 { if(a[1].nsm<x)//判断女神时间是否有空余 printf("wait for me\n"); else { ans = query(1,x,1,n,1);//先查找位置 insert(1,ans,ans+x-1,1,n,1);//然后对其区间进行更新 printf("%d,don't put my gezi\n",ans); } } else { ans = query(0,x,1,n,1); insert(1,ans,ans+x-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); printf("I am the hope of chinese chengxuyuan!!\n"); } } } return 0;}
阅读全文
0 0
- HDU4553:约会安排(线段树)(第三部分 区间合并)
- HDU4553:约会安排(线段树区间合并)
- hdu4553约会安排 线段树
- HDU4553(线段树区间合并)
- 线段树之HDU4553 约会安排
- HDU - 4553 约会安排(线段树 区间合并)
- HDU 4553 约会安排(线段树区间合并)
- HDU 4553 约会安排 (线段树 -- 区间合并(多种优先级的区间合并) )
- hdoj 4553 约会安排 【线段树区间合并】
- HDU 4553 约会安排(线段树区间合并&优先级)
- hdu4553----约会安排
- HDU4553约会安排
- HDU 4553:约会安排(区间合并)
- POJ 3667 hotel (线段树)(第三部分 区间合并)
- hdu 3308 LCIS(线段树)(第三部分 区间合并)
- hdu 1540 Tunnel Warfare(线段树)(第三部分 区间合并)
- HDU-4553-约会安排(线段树维护最长连续区间)
- hdu4553(神TM烦的线段树维护连续区间ORZ)
- Python copy()与deepcopy()区别,深拷贝与浅拷贝
- Maven学习笔记(二)-仓库
- busybox menuconfig配置
- [实战]Ubuntu桥接无法连接外网问题
- python学习笔记(2)——list&tuple
- HDU4553:约会安排(线段树)(第三部分 区间合并)
- 猜数字游戏
- 图像分割:阈值获取方法总结
- Android7.0新特性
- 跑R-FCN遇到的所有的坑(合集)
- Linux运行firefox出错
- TCP/IP详解学习笔记(6)-UDP协议
- springboot 集成disconf
- Q_Learning算法的一个简单的应用。