看到讲课安排上 线段树有一节课"区间合并" 我是迷茫的 因为并没有见过

然后了解了一下题目 发现以前写过 还是很麻烦的树链剖分 大概是 解决带修改的区间查询"连续问题"

意思就是给一个数组 要对这个数组进行修改 然后进行区间查询 查询的一般是 l r 区间内的 连续xx 可能是LCIS 也可能只是连续的数字..

解题的方法比较固定 由于是 连续性 相关 所以对于每个数组 维护它的左边与右边与全局的性质 例如紧靠左(右)边连续xx的长度和这个区间内连续xx的最长长度

关键就在up函数上 不管是单点还是区间修改 都能通过up来做巧妙地构造

POJ 3667

每次清空一段 或 查询一段中最靠左的x长度并填补

维护每个区间的左右连续 最简单的区间合并

HDU 3308

单点修改 或 查询一段中的LCIS

与上一道题的差别就是up函数 和 query函数中 对于 一个区间的两个子区间合并 需要判断一下数字的大小关系

HDU 3397

01串 区间赋值 区间反转 查询 区间sum 和 区间连续1的maxlen

同时维护左右全局的0和1的长度 在做反转的时候直接交换就可以了

在down的时候 如果down下去的是一个反转的历史 它可能会和上一次的历史发生化合 上一次的历史是赋值0 那这一次的历史就覆盖成赋值1而不是反转

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<map>
#include<vector>
#include<queue>
using namespace std;
const int maxn = 100050 ;
int n , m ;
struct node {
int rl1, ll1, tl1 ;
int rl0, ll0, tl0 ;
int sum ;
int l , r ;
int len;
}a[maxn * 4];
int mark[maxn * 4] ; /// 0 -> 0 1 -> 0 -1 notdid 2 -> ycy
int b[maxn] ;
void up(int p) {
if(a[p].l == a[p].r )return ;
int pl = p*2 , pr = p*2+1 ;
a[p].tl0 = max(a[pl].tl0 , a[pr].tl0) ;
a[p].tl0 = max(a[p].tl0 , a[pl].rl0 + a[pr].ll0) ;
a[p].tl1 = max(a[pl].tl1 , a[pr].tl1) ;
a[p].tl1 = max(a[p].tl1 , a[pl].rl1 + a[pr].ll1) ; a[p].ll0 = a[pl].ll0;
if(a[pl].sum == 0 ) {
a[p].ll0 = max(a[p].ll0 , a[pl].len + a[pr].ll0) ;
}
a[p].rl0 = a[pr].rl0;
if(a[pr].sum == 0 ) {
a[p].rl0 = max(a[p].rl0 , a[pr].len + a[pl].rl0) ;
} a[p].ll1 = a[pl].ll1;
if(a[pl].sum == a[pl].len ) {
a[p].ll1 = max(a[p].ll1 , a[pl].len + a[pr].ll1) ;
}
a[p].rl1 = a[pr].rl1;
if(a[pr].sum == a[pr].len ) {
a[p].rl1 = max(a[p].rl1 , a[pr].len + a[pl].rl1) ;
}
a[p].sum = a[pl].sum + a[pr].sum ;
return ;
}
void build(int p,int l,int r){
mark[p] = -1 ;
a[p].l = l , a[p].r = r;
if(b[l] == 0) a[p].ll0 = 1 , a[p].ll1 = 0; else a[p].ll0 = 0 , a[p].ll1 = 1;
if(b[r] == 0) a[p].rl0 = 1 , a[p].rl1 = 0; else a[p].rl0 = 0 , a[p].rl1 = 1;
if(b[l] == 0) a[p].tl0 = 1 , a[p].tl1 = 0; else a[p].tl0 = 0 , a[p].tl1 = 1;
a[p].len = r - l + 1 ;
if(b[l] == 0)a[p].sum = 0 ; else a[p].sum = 1 ;
if(l == r)return ;
int mid = (l+r) / 2 ;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
up(p);
}
void ycy(int p) {
swap(a[p].ll0 , a[p].ll1) ;
swap(a[p].rl0 , a[p].rl1) ;
swap(a[p].tl0 , a[p].tl1) ;
a[p].sum = a[p].len - a[p].sum ;
}
void down(int p) {
if(a[p].l == a[p].r)return ;
if(mark[p] == -1)return ;
int pl = p*2 , pr = p*2+1 ;
if(mark[p] == 0) {
mark[pl] = mark[pr] = mark[p] ;
a[pl].ll0 = a[pl].rl0 = a[pl].tl0 = a[pl].len ;
a[pl].ll1 = a[pl].rl1 = a[pl].tl1 = a[pl].sum = 0 ;
a[pr].ll0 = a[pr].rl0 = a[pr].tl0 = a[pr].len ;
a[pr].ll1 = a[pr].rl1 = a[pr].tl1 = a[pr].sum = 0 ;
}
else if(mark[p] == 1){
mark[pl] = mark[pr] = mark[p] ;
a[pl].ll0 = a[pl].rl0 = a[pl].tl0 = 0 ;
a[pl].ll1 = a[pl].rl1 = a[pl].tl1 = a[pl].sum = a[pl].len ;
a[pr].ll0 = a[pr].rl0 = a[pr].tl0 = 0 ;
a[pr].ll1 = a[pr].rl1 = a[pr].tl1 = a[pr].sum = a[pr].len ;
}
else {
if(mark[pl] == 0) mark[pl] = 1;
else if(mark[pl] == 1) mark[pl] = 0 ;
else if(mark[pl] == 2) mark[pl] = -1 ;
else mark[pl] = 2;
if(mark[pr] == 0) mark[pr] = 1;
else if(mark[pr] == 1) mark[pr] = 0 ;
else if(mark[pr] == 2) mark[pr] = -1 ;
else mark[pr] = 2;
ycy(pl) , ycy(pr) ;
}
mark[p] = -1 ;
}
void upda1(int p , int l , int r ){ /// 0
if(a[p].l >= l && a[p].r <= r) {
mark[p] = 0 ;
a[p].ll0 = a[p].rl0 = a[p].tl0 = a[p].len ;
a[p].ll1 = a[p].rl1 = a[p].tl1 = a[p].sum = 0 ;
return ;
}
if(a[p].l == a[p].r)return ;
down(p) ;
int mid = (a[p].l + a[p].r) / 2 ;
if(r <= mid) {
upda1(p*2,l,r) ;
}
else if(l >= mid+1) {
upda1(p*2+1,l,r);
}
else {
upda1(p*2,l,mid);
upda1(p*2+1,mid+1,r);
}
up(p);
}
void upda2(int p , int l , int r ){ /// 1
if(a[p].l >= l && a[p].r <= r) {
mark[p] = 1 ;
a[p].ll0 = a[p].rl0 = a[p].tl0 = 0 ;
a[p].ll1 = a[p].rl1 = a[p].tl1 = a[p].sum = a[p].len ;
return ;
}
if(a[p].l == a[p].r)return ;
down(p) ;
int mid = (a[p].l + a[p].r) / 2 ;
if(r <= mid) {
upda2(p*2,l,r) ;
}
else if(l >= mid+1) {
upda2(p*2+1,l,r);
}
else {
upda2(p*2,l,mid);
upda2(p*2+1,mid+1,r);
}
up(p);
}
void upda3(int p, int l , int r ){
down(p);
if(a[p].l >= l && a[p].r <= r) {
ycy(p) ;
mark[p] = 2 ;
return ;
}
if(a[p].l == a[p].r) return ;
int mid = (a[p].l + a[p].r) / 2;
if(r <= mid) {
upda3(p*2,l,r);
}
else if(l >= mid +1) {
upda3(p*2+1,l,r);
}
else {
upda3(p*2,l,mid);
upda3(p*2+1,mid+1,r);
}
up(p);
}
int query1(int p,int l,int r){
down(p);
if(a[p].l>=l&&a[p].r<=r) return a[p].sum;
int mid = (a[p].l+a[p].r)/2;
if(r<=mid)return query1(p*2,l,r);
else if(l>=mid+1)return query1(p*2+1,l,r);
else return query1(p*2,l,r) + query1(p*2+1,l,r);
}
int query2(int p,int l,int r){
down(p);
if(a[p].l>=l&&a[p].r<=r)return a[p].tl1 ;
if(a[p].l == a[p].r)return a[p].tl1;
int mid = (a[p].l + a[p].r) / 2 ;
if(r <= mid) {
return query2(p*2,l,r);
}
else if(l >= mid+1)
return query2(p*2+1,l,r);
else {
int res = 0;
int r1 = r ;
int r2 = a[p*2+1].l + a[p*2+1].ll1 - 1;
r1 = min(r2,r1) ;
int l1 = l ;
int l2 = a[p*2].r - a[p*2].rl1 + 1;
l1 = max(l1,l2) ;
if(r1 >= l1)
res = max(res , r1-l1+1);
res = max(query2(p*2,l,r),res) ;
res = max(query2(p*2+1,l,r),res);
return res ;
}
}
int main(){
int t;
scanf("%d",&t);
while(t-- ){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",&b[i]) ;
build(1,1,n) ;
for(int i=1;i<=m;i++){
int op;
scanf("%d",&op);
int A,B;
scanf("%d%d",&A,&B);
A++,B++;
if(op==0){
upda1(1,A,B);
}
else if(op==1){
upda2(1,A,B);
}
else if(op==2){
upda3(1,A,B);
}
else if(op==3){
printf("%d\n",query1(1,A,B));
}
else {
printf("%d\n",query2(1,A,B));
}
}
}
}

感觉区间合并是一个线段树的思路

学习了kd-tree之后对线段树有了新的认识

POJ 3667 & HDU 3308 & HDU 3397 线段树的区间合并的更多相关文章

  1. 线段树的区间合并 B - LCIS

    B - LCIS HDU - 3308 这个是一个很简单很明显的线段树的区间合并,不过区间合并的题目都还是有点难写,建议存个板子. #include <cstdio> #include & ...

  2. 线段树:CDOJ1592-An easy problem B (线段树的区间合并)

    An easy problem B Time Limit: 2000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) Pr ...

  3. (简单) HDU 3308 LCIS,线段树+区间合并。

    Problem Description Given n integers. You have two operations: U A B: replace the Ath number by B. ( ...

  4. Codeforces Round #222 (Div. 1) D. Developing Game 线段树有效区间合并

    D. Developing Game   Pavel is going to make a game of his dream. However, he knows that he can't mak ...

  5. CodeForces - 587E[线段树+线性基+差分] ->(线段树维护区间合并线性基)

    题意:给你一个数组,有两种操作,一种区间xor一个值,一个是查询区间xor的结果的种类数 做法一:对于一个给定的区间,我们可以通过求解线性基的方式求出结果的种类数,而现在只不过将其放在线树上维护区间线 ...

  6. HDU 3308 LCIS(线段树)

    Problem Description Given n integers.You have two operations:U A B: replace the Ath number by B. (in ...

  7. HDU 2795 Billboard 【线段树维护区间最大值&&查询变形】

    任意门:http://acm.hdu.edu.cn/showproblem.php?pid=2795 Billboard Time Limit: 20000/8000 MS (Java/Others) ...

  8. 2016 Multi-University Training Contest 10 [HDU 5861] Road (线段树:区间覆盖+单点最大小)

    HDU 5861 题意 在n个村庄之间存在n-1段路,令某段路开放一天需要交纳wi的费用,但是每段路只能开放一次,一旦关闭将不再开放.现在给你接下来m天内的计划,在第i天,需要对村庄ai到村庄bi的道 ...

  9. hdu 1556 涂气球 线段树(区间更新~对区间[x,y]更新,求任意节点被更新的次数)

    Color the ball Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

随机推荐

  1. 带参数的main函数

    带参数的main函数 int main(int argc,char **argv)  或int main(int argc,char *argv[])  /*解析 依据<C程序设计语言(第二版. ...

  2. codevs1068 乌龟棋==洛谷P1541 乌龟棋

    P1541 乌龟棋 题目背景 小明过生日的时候,爸爸送给他一副乌龟棋当作礼物. 题目描述 乌龟棋的棋盘是一行N个格子,每个格子上一个分数(非负整数).棋盘第1格是唯一的起点,第N格是终点,游戏要求玩家 ...

  3. explain the past and guide the future 好的代码的标准:解释过去,指引未来;

    好的代码的标准:解释过去,指引未来: Design philosophies | Django documentation | Django https://docs.djangoproject.co ...

  4. 报表生成之Hyperion SQR

    SQR(Structured Query Reporter)是为从数据库管理系统生成报告而设计的一种编程语言.名称是结构化查询报告的缩写,这表明它与SQL(结构化查询语言)的关系.任何SQL语句可以嵌 ...

  5. VCL控件组件大都应该重载TWinControl的虚函数WndProc来进行处理窗口消息的工作

    TWinControl的构造函数中会调用MakeObjectInstance并且传递MainWndProc作为窗口消息处理函数,而MainWndProc则会调用虚函数WndProc来处理窗口消息.留个 ...

  6. 阻止element组件中的<el-input/>的粘贴功能

    需求: 阻止element组件中的<el-input/>的粘贴功能 实现思路: <el-input/>组件是由外层<div>和内层的<input>组成的 ...

  7. Selenium获取input输入框中值的几种方法

    1.selenium 自带的方法 get_attribute('value') driver.find_element_by_name("f[url]").get_attribut ...

  8. ABAP rfc 发布webservice 错误

    一.SICF 测试服务报错: 哎呀,找不到网页! 网站在检索此网址时出现错误.托管此网站的服务器可能关闭进行维护或配置不正确. HTTP ERROR 500

  9. 深入理解MVC架构

    MVC MVC是一种设计模式(Design pattern),也就是一种解决问题的方法和思路, 是上世纪80年代提出的,到现在已经颇有历史了. MVC的意义在于指导开发者将数据与表现解耦,提高代码,特 ...

  10. Android:日常学习笔记(7)———探究UI开发(4)

    Android:日常学习笔记(7)———探究UI开发(4) UI概述  View 和 ViewGrou Android 应用中的所有用户界面元素都是使用 View 和 ViewGroup 对象构建而成 ...