博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
POJ 3667 线段树的区间合并简单问题
阅读量:4455 次
发布时间:2019-06-07

本文共 3358 字,大约阅读时间需要 11 分钟。

题目大意:

有一排标号1-N的房间。
操作一:询问是不是有连续长度为a的空房间,有的话住进最左边(占用a个房间)
操作二:将[a,a+b-1]的房间清空(腾出b个房间)
思路:记录每个区间中“靠左”“靠右”“中间”的空房间
线段树操作:update:区间替换
query:询问满足条件的最左端点

题目链接:

题目操作:

因为这里找从最左边住起的房间,所以这里不能像常规地写query函数那样写了,终于发现自己只会套模板的下场的悲哀了,智商拙计啊T T

而且你在query函数,因为要尽可能找左边的房间,所以要从左边先递归

1.

int query(int cur,int x,int y,int w)

{
    int mid=(x+y)>>1,ls=cur<<1,rs=cur<<1|1;
    if(x==y) return x //这里是表示找到树的底层无叶节点了就结束函数,同时也防止找不到点,其实这里如果找不到所求点的话,会不断进入右子树最后抵达最大的子节点返回
    pushdown(cur,x,y);
    if(mc[cur<<1]>=w) return query(ls,x,mid,w);  //如果左侧能找到满足的点,我们不断朝左侧进行递归
    else if(rc[cur<<1]+lc[cur<<1|1]>=w) return mid-rc[cur<<1]+1;//左侧不成立我们在开始找中间并在一起形成的房间的最左侧点
    return query(rs,mid+1,y,w);  //左侧中间都不成立,那么只能进入右子树进行找点
}
因为这个query函数必然有返回值,所以,我们在主函数中必须先进行判断能否找到适合的一连串的房间,然后再进行ans=query(1,1,n,w)操作以及后面的房间入住的覆盖操作。

这个判断很简单 1为线段树根节点,所以mc[1]其实是最大的连续最长房间,if(mc[1]>=w)这个判断执行就可以了

这里介绍一下puts("0"):

puts()函数用来向标准输出设备()写字符串并换行,其调用方式为,puts(s);其中s为字符串字符(字符串名或字符串)。

所以这道题puts("0");就输出了不存在的情况

2.

当然我也可以换种方式在query的函数里面进行一下小小的修改,使得它在不能找到房间的时候输出-1;

int query(int cur,int x,int y,int w)

{
    int mid=(x+y)>>1,ls=cur<<1,rs=cur<<1|1;
    if(x==y) return mc[cur]<w?-1:x; //在这修改一下,然后直接在main函数中判断为-1,那么输出0即可
    pushdown(cur,x,y);
    if(mc[cur<<1]>=w) return query(ls,x,mid,w);
    else if(rc[cur<<1]+lc[cur<<1|1]>=w) return mid-rc[cur<<1]+1;
    return query(rs,mid+1,y,w);
}

总代码如下:

1 #include 
2 #include
3 #include
4 using namespace std; 5 #define N 50010 6 #define L ls,x,mid 7 #define R rs,mid+1,y 8 int rev[N<<2],lc[N<<2],rc[N<<2],mc[N<<2]; 9 void update(int cur,int x,int y)10 {11 int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1;12 lc[cur]=lc[ls],rc[cur]=rc[rs];13 mc[cur]=max(mc[ls],mc[rs]);14 mc[cur]=max(mc[cur],rc[ls]+lc[rs]);15 if(lc[ls]==mid-x+1) lc[cur]=lc[ls]+lc[rs];16 if(rc[rs]==y-mid) rc[cur]=rc[rs]+rc[ls];17 }18 void build(int cur,int x,int y)19 {20 int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1;21 rev[cur]=-1;22 if(x==y){23 lc[cur]=rc[cur]=mc[cur]=1;24 return;25 }26 build(ls,x,mid);27 build(rs,mid+1,y);28 update(cur,x,y);29 }30 void pushdown(int cur,int x,int y)31 {32 int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1;33 if(rev[cur]!=-1){34 if(rev[cur]==1){35 rev[ls]=rev[rs]=1;36 lc[ls]=rc[ls]=mc[ls]=lc[rs]=rc[rs]=mc[rs]=0;37 rev[cur]=-1;38 }39 else if(rev[cur]==0){40 rev[ls]=rev[rs]=0;41 lc[ls]=rc[ls]=mc[ls]=mid-x+1;42 lc[rs]=rc[rs]=mc[rs]=y-mid;43 rev[cur]=-1;44 }45 }46 }47 void change(int cur,int x,int y,int s,int t,int v)48 {49 int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1;50 if(x>=s&&y<=t){51 rev[cur]=v;52 lc[cur]=rc[cur]=mc[cur]=v?0:y-x+1;53 return;54 }55 pushdown(cur,x,y);56 if(mid>=s) change(ls,x,mid,s,t,v);57 if(mid+1<=t) change(rs,mid+1,y,s,t,v);58 update(cur,x,y);59 }60 int query(int cur,int x,int y,int w)61 {62 int mid=(x+y)>>1,ls=cur<<1,rs=cur<<1|1;63 if(x==y) return x;64 pushdown(cur,x,y);65 if(mc[cur<<1]>=w) return query(ls,x,mid,w);66 else if(rc[cur<<1]+lc[cur<<1|1]>=w) return mid-rc[cur<<1]+1;67 return query(rs,mid+1,y,w);68 }69 int main()70 {71 int n,m,op,a,b;72 while(scanf("%d%d",&n,&m)!=EOF){73 build(1,1,n);74 for(int i=0;i

 

转载于:https://www.cnblogs.com/CSU3901130321/p/3897393.html

你可能感兴趣的文章
vue-cli3 中console.log报错
查看>>
GridView 中Item项居中显示
查看>>
UML类图五种关系与代码的对应关系
查看>>
如何理解作用域
查看>>
从无到满意offer,你需要知道的那些事
查看>>
P1516 青蛙的约会 洛谷
查看>>
SDOI2011 染色
查看>>
JQuery EasyUI combobox动态添加option
查看>>
面向连接的TCP概述
查看>>
前端快捷方式 [记录]
查看>>
亲测可用,解决端口被占用的指令!!
查看>>
MySQL--视图、触发器、事务、存储过程、内置函数、流程控制、索引
查看>>
Django--数据库查询操作
查看>>
自定义配置文件的使用
查看>>
js-20170609-运算符
查看>>
算法笔记_065:分治法求逆序对(Java)
查看>>
MSP430FLASH小结
查看>>
STM32 ADC转换时间
查看>>
结合实际业务场景聊一聊MVP模式的应用
查看>>
我爱 哐 哐 哐,我是哐人类!-【废话区】
查看>>