题意: 给定长度为n的区间 ,有2个操作:

操作1: 在区间中靠左放k个元素,输出新放入元素中最左边的位置,如果放不下输出 0;

操作2 : 清空 l 到 l+w-1这一段区间的元素

这里有一个状态转移方程(即线段树的上推方式):

线段树区间pos中储存  lcon--从区间左端L最大连续的区间长度 , rcon--从线段树右端R最大连续的区间长度 ,mcon 区间内最大的区间长度

则:      t[pos].mcon = max{ t[Lpos].rcon+t[Rpos].lcon  ,t[Lpos].mcon  ,t[Rpos].mcon );

t[pos].lcon = t[Lpos].lcon+(t[Rpos],lcon);  t[pos].rcon = t[Rpos].rcon+(t[Lpos].rcon) (如果左或右区间整段连续,就加上括号里面的部分

lazy标记的下移(对整段空或整段满的区间进行标记):

void pushdown( int L ,int R, int pos){if( t[pos].tag!=0 && t[pos].tag!=1 ) return ;int Mid;t[posl].tag = t[posr].tag =t[pos].tag;t[posl].mcon = t[posl].lcon = t[posl].rcon = t[pos].tag ? mid - L+1 : 0 ;t[posr].mcon = t[posr].lcon = t[posr].rcon = t[pos].tag ? R-mid : 0 ;t[pos].tag = -1;return ;
}

查询:

判断能否放下: 比较k与总区间最大连续区间长度t[ 1 ].mcon 的大小

查询新放入元素最左坐标:如果左区间最大连续空区间大于目标长度就一直查询左区间,直到查询不了就判断左区间右连续加上右区间左连续可不可以,可以就输出结果,不行的话在查询右区间

int query(  int L ,int R ,int pos ,int w ){if( L==R ) return L;// cout<< L <<' '<<R << ' '<<w<<endl;
     pushdown( L ,R ,pos);int Mid;if( t[posl].mcon >= w ) return query( lson , w);                                           //优先查左边else if( t[posl].rcon + t[posr].lcon >= w) return mid - t[posl].rcon +1 ; //查到左边放不下了,输出区间放在中间的结果else return query( rson ,w);                                                                            //中间放不了,最末查询右边
}

更新比较平常 ,就不说了

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
#define posl pos<<1
#define posr pos<<1|1
#define lson L ,mid ,posl
#define rson mid+1 ,R ,posr
#define Mid mid=(L+R)>>1struct tree{int lcon ,rcon ,mcon;int  tag;
} t[50005<<2];
void pushup( int L ,int R ,int pos){t[pos].lcon = t[posl].lcon;t[pos].rcon = t[posr].rcon;int Mid;if( t[pos].lcon == mid - L +1 ) t[pos].lcon += t[posr].lcon;if( t[pos].rcon == R - mid ) t[pos].rcon += t[posl].rcon;t[pos].mcon = max( t[posl].rcon+t[posr].lcon ,max( t[posl].mcon  ,t[posr].mcon));
}void pushdown( int L ,int R, int pos){if( t[pos].tag!=0 && t[pos].tag!=1 ) return ;int Mid;t[posl].tag = t[posr].tag =t[pos].tag;t[posl].mcon = t[posl].lcon = t[posl].rcon = t[pos].tag ? mid - L+1 : 0 ;t[posr].mcon = t[posr].lcon = t[posr].rcon = t[pos].tag ? R-mid : 0 ;t[pos].tag = -1;return ;
}void build( int L ,int R ,int pos){t[pos].tag = -1;t[pos].lcon = t[pos].rcon = t[pos].mcon = R - L +1;if( L == R) return ;int Mid;build( lson);build( rson);
}void updata( int L ,int R ,int pos ,int l,int r,int v ){if( L>= l && R <= r ){t[pos].mcon = t[pos].rcon = t[pos].lcon = v ? R - L +1 : 0 ;t[pos].tag = v;return ;}if( L == R)return;pushdown( L ,R ,pos);int Mid;if( l <= mid ) updata( lson ,l ,r ,v);if( mid < r) updata( rson ,l ,r ,v);pushup( L ,R ,pos);
}int query(  int L ,int R ,int pos ,int w ){if( L==R ) return L;// cout<< L <<' '<<R << ' '<<w<<endl;
     pushdown( L ,R ,pos);int Mid;if( t[posl].mcon >= w ) return query( lson , w);                                           //优先查左边else if( t[posl].rcon + t[posr].lcon >= w) return mid - t[posl].rcon +1 ; //查到左边放不下了,输出区间放在中间的结果else return query( rson ,w);                                                                            //中间放不了,最末查询右边
}
int main( ){int n,m;scanf( "%d%d" ,&n ,&m);build( 1 ,n ,1);while( m-- ){int op ,k ,l ,r;scanf("%d" ,&op);if( op ==1){scanf("%d" ,&k);if( t[1].mcon >=k){l=query( 1 ,n ,1 ,k);updata( 1 , n ,1 ,l ,l+k-1, 0);printf("%d\n" ,l);}else printf("0\n");}else{scanf("%d%d",&l ,&r);updata( 1 ,n ,1 ,l ,l+r-1,1);}}return 0;
}

转载于:https://www.cnblogs.com/-ifrush/p/10632421.html

Hotel POJ - 3667(线段树 + 区间合并相关推荐

  1. poj-3667(线段树区间合并)

    题目链接:传送门 参考文章:传送门 思路:线段树区间合并问题,每次查询到满足线段树的区间最左值,然后更新线段树. #include<iostream> #include<cstdio ...

  2. 树链剖分——线段树区间合并bzoj染色

    线段树区间合并就挺麻烦了,再套个树链就更加鬼畜,不过除了代码量大就没什么其他的了.. 一些细节:线段树每个结点用结构体保存,pushup等合并函数改成返回一个结构体,这样好写一些 struct Seg ...

  3. SPOJ GSS3-Can you answer these queries III-分治+线段树区间合并

    Can you answer these queries III SPOJ - GSS3 这道题和洛谷的小白逛公园一样的题目. 传送门: 洛谷 P4513 小白逛公园-区间最大子段和-分治+线段树区间 ...

  4. Tunnel Warfare(HDU1540+线段树+区间合并)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1540 题目: 题意:总共有n个村庄,有q次操作,每次操作分为摧毁一座村庄,修复一座村庄,和查询与询问的 ...

  5. CodeForces - 1539F Strange Array(线段树区间合并)

    题目链接:点击查看 题目大意:给出一个长度为 nnn 的序列,规定位置 iii 的贡献是:设 x=a[i]x=a[i]x=a[i],选择一个包含 iii 的区间 [l,r][l,r][l,r],将其中 ...

  6. 牛客 - 求函数(线段树+区间合并/线段树+矩阵维护)

    题目链接:点击查看 题目大意:现在有 n 个函数,每个函数都是诸如 f( x ) = k * x + b 的形式,只是每个函数的 k 和 b 都是相互独立的,现在给出两个操作: 1 pos k b:将 ...

  7. 2021牛客暑期多校训练营7 xay loves monotonicity 线段树区间合并

    传送门 文章目录 题意: 思路: 题意: 题面挺绕口的,还是看原题比较好. 大概的意思就是让你从给定的区间中选择一个以左端点为起点的一个上升子序列,让后将这些下标存下来,在bbb中将这些位置拿出来后, ...

  8. HDU3308 线段树区间合并

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3308 ,简单的线段树区间合并. 线段树的区间合并:一般是要求求最长连续区间,在PushUp()函数中实 ...

  9. HDU1540(线段树区间合并)

    很经典的一道题,线段树区间合并非常好的一道入门题,每个节点保存区间连续1的最大左串长度,最大右串长度,以及区间最大长度(常规的三种信息维护),更新操作时注意push_up函数,针对不同的问题,push ...

最新文章

  1. SecureCRT 6.7.1 注冊机 和谐 破解 补丁 方法
  2. java 访问手机存储卡,Android App将数据写入内部存储和外部存储的示例
  3. 8086CPU汇编:一般的标号与直接定址标号
  4. jdbc时区_什么比日期和时区更难? SQL / JDBC中的日期和时区!
  5. Servlet - Listener、Filter、Decorator
  6. Sql server 数据转到 Mysql 数据库
  7. 【英语学习】【WOTD】mirandize 释义/词源/示例
  8. Ubuntu 服务器设置软件多用户访问
  9. 娱乐篇第十期:互联网的事情you意思(十)
  10. 电脑有网络,但所有浏览器网页都打不开,是怎么回事?
  11. 数字图像处理技术与人脸识别
  12. 安卓永久修改像素密度
  13. 2023中南大学计算机考研信息汇总
  14. java 读取word 表格,java读取word表格方法
  15. 【STM32】IO引脚复用器和映射原理与配置
  16. 这个社会最大的现实是“大鱼吃小鱼,小鱼吃虾米”
  17. 科技新品 | 索尼可换镜头Vlog相机;LG电子全球首款卷曲屏电视;卡西欧《吃豆人》合作款数码手表...
  18. Wordpress网站备份
  19. facebook有哪些信息_如何让人们不知道您在Facebook上阅读了他们的信息
  20. 从OA到COP,致远互联成引领行业的“灯塔”

热门文章

  1. RocketMQ 顺序消费只消费一次 坑
  2. 用easymock来mock数据
  3. Oracle对表空间、用户、用户权限的操作
  4. 百度地图api公交路线,IE下跳转百度地图后中文变成乱码的解决办法
  5. dede织梦数据表字段解释
  6. JMX 简介 和 实例
  7. Mobile Lua 6.5 发布,MoSync 的 Lua 移植版本
  8. [TJOI2017]异或和
  9. 窗口限制文件上传格式
  10. 通过NavMeshObstacle解决NavMesh防卡