两道题都是线段树的区间合并

lsum, rsum分别表示左/右端点 开始向右/左 符合条件的元素的最长连续长度

sum表示这个区间的符合条件的元素的最长连续长度

所以pushUp可写:

 void pushUp(int root, int l, int r)
{
int len = r - l + ;
int lenr = len >> , lenl = len - lenr;
lsum[root] = lsum[lson];
rsum[root] = rsum[rson];
if (lsum[root] == lenl) lsum[root] += lsum[rson];
if (rsum[root] == lenr) rsum[root] += rsum[lson];
sum[root] = max(rsum[lson]+lsum[rson], max(sum[lson], sum[rson]));
}

更新时 根据更新的元素的值 可以确定 这个区间的sum lsum 和 rsum 是len 还是 0

所以pushDown 和 update可以写了

这里放pushDown

 void pushDown(int root, int l, int r)
{
int len = r - l + ;
int lenr = len >> , lenl = len - lenr;
if (setmark[root] != -)
{
int v = setmark[root];
setmark[lson] = setmark[rson] = v;
setmark[root] = -;
lsum[lson] = rsum[lson] = sum[lson] = v ? : lenl;//被占用是1 不被占用是0
lsum[rson] = rsum[rson] = sum[rson] = v ? : lenr;
}
}

另外注意的是query的方式

 int query(int root, int l, int r, int qlen)
{
if (l == r) return l;
pushDown(root, l, r);
int mid = (l+r) >> ;
if (sum[lson] >= qlen) return query(lson, l, mid, qlen);
else if (rsum[lson]+lsum[rson] >= qlen) return mid-rsum[lson]+;//左区间的右半部份 和右区间的左半部份
else if return query(rson, mid+, r, qlen);
}

如果不存在直接求sum[1]是否>=qlen

POJ3667

元素只有1 和 0两种情况 用一个维护一个区间最长连续和即可

代码君:

 #include <string.h>
#include <stdio.h>
#include <algorithm>
#include <iostream>
#define lson root<<1
#define rson root<<1|1
#define fi first
#define se second
#define pb push_back
#define po pop_back typedef long long ll; const int MAXN = ;
const int MAXM = ;
const int INF = 0x3f3f3f3f; using namespace std; int n, m;
int sum[MAXN << ];
int setmark[MAXN << ];
int lsum[MAXN << ];
int rsum[MAXN << ]; void pushUp(int root, int l, int r)
{
int len = r - l + ;
int lenr = len >> , lenl = len - lenr;
lsum[root] = lsum[lson];
rsum[root] = rsum[rson];
if (lsum[root] == lenl) lsum[root] += lsum[rson];
if (rsum[root] == lenr) rsum[root] += rsum[lson];
sum[root] = max(rsum[lson]+lsum[rson], max(sum[lson], sum[rson])); //这个地方 理解!
}
void build(int root, int l, int r)
{
int len = r-l+;
setmark[root] = -;
lsum[root] = rsum[root] = sum[root] = len;
if (l == r) return ;
int mid = (l+r) >> ;
build(lson, l, mid);
build(rson, mid+, r);
pushUp(root, l, r);
}
void pushDown(int root, int l, int r)
{
int len = r - l + ;
int lenr = len >> , lenl = len - lenr;
if (setmark[root] != -)
{
int v = setmark[root];
setmark[lson] = setmark[rson] = v;
setmark[root] = -;
lsum[lson] = rsum[lson] = sum[lson] = v ? : lenl;//被占用是1 不被占用是0
lsum[rson] = rsum[rson] = sum[rson] = v ? : lenr;
}
}
void update(int root, int l, int r, int ul, int ur, int val)
{
int len = r - l + ;
int lenr = len >> , lenl = len - lenr;
if (l > ur || r < ul) return ;
if (l >= ul && r <= ur)
{
setmark[root] = val;
lsum[root] = rsum[root] = sum[root] = val ? : len;
return ;
}
pushDown(root, l, r);
int mid = (l+r) >> ;
update(lson, l, mid, ul, ur, val);
update(rson, mid+, r, ul, ur, val);
pushUp(root, l, r);
}
int query(int root, int l, int r, int qlen)
{
if (l == r) return l;
pushDown(root, l, r);
int mid = (l+r) >> ;
if (sum[lson] >= qlen) return query(lson, l, mid, qlen);
if (rsum[lson]+lsum[rson] >= qlen) return mid-rsum[lson]+;//左区间的右半部份 和右区间的左半部份
if (sum[rson] >= qlen) return query(rson, mid+, r, qlen);
return -;
}
int main()
{
//freopen("in.txt", "r", stdin);
while (cin >> n >> m)
{
build(, , n);
for(int i = ; i < m; i++)
{
int op, p, l;
scanf("%d", &op);
if (op == )
{
scanf("%d", &l);
if (sum[] < l)
{
puts("");
continue;
}
int pos = query(, , n, l);
cout << pos << endl;
update(, , n, pos, pos+l-, );
}
else
{
scanf("%d%d", &p, &l);
//cout << p << " " << p+l-1 << endl;
update(, , n, p, p+l-, );
}
}
}
return ;
}

HDU4553

元素有0 1 2三种情况 需要维护两个区间最长连续和

代码君:

 #include <bits/stdc++.h>
#define lson root<<1
#define rson root<<1|1
#define fi first
#define se second
#define pb push_back
#define po pop_back using namespace std; typedef long long ll;
typedef pair<int, int> P; const int MAXN = 1e5+;
const int MAXM = 1e5+;
const int INF = 0x3f3f3f3f; //0 for diaosi 1 for nvshen
int sum[][MAXN << ];
int lsum[][MAXN << ];
int rsum[][MAXN << ];
int setmark[MAXN << ];
int pos = -;
int qlen = -;
int n, m;
void pushUp(int root, int l, int r, int nu)
{
int len = r-l+;
int lenr = len >> , lenl = len - lenr;
lsum[nu][root] = lsum[nu][lson];
if (lsum[nu][root] == lenl) lsum[nu][root] += lsum[nu][rson];
rsum[nu][root] = rsum[nu][rson];
if (rsum[nu][root] == lenr) rsum[nu][root] += rsum[nu][lson];
sum[nu][root] = max(rsum[nu][lson]+lsum[nu][rson], max(sum[nu][lson], sum[nu][rson]));
}
void build(int root, int l, int r)
{
int len = r - l + ;
setmark[root] = -;
for (int i = ; i < ; i++)
{
sum[i][root] = lsum[i][root] = rsum[i][root] = len;
}
if (l == r) return ;
int mid = (l+r) >> ;
build(lson, l, mid);
build(rson, mid+, r);
for (int i = ; i < ; i++)
pushUp(root, l, r, i);
}
void pushDown(int root, int l, int r)
{
int len = r - l + ;
int lenr = len >> , lenl = len - lenr;
if (setmark[root] != -)
{
int val = setmark[root];
setmark[lson] = setmark[rson] = val;
setmark[root] = -;
lsum[][lson] = rsum[][lson] = sum[][lson] = (val == ? lenl : );
lsum[][rson] = rsum[][rson] = sum[][rson] = (val == ? lenr : );
lsum[][lson] = rsum[][lson] = sum[][lson] = ( (val == || val == ) ? lenl : );
lsum[][rson] = rsum[][rson] = sum[][rson] = ( (val == || val == ) ? lenr : );
}
}
void update(int root, int l, int r, int ul, int ur, int val)
{
int len = r - l + ;
if (l > ur || r < ul) return;
if (l >= ul && r <= ur)
{
setmark[root] = val;
lsum[][root] = rsum[][root] = sum[][root] = (val == ? len : );
lsum[][root] = rsum[][root] = sum[][root] = ((val == || val == ) ? len : );
return ;
}
pushDown(root, l, r);
int mid = (l+r) >> ;
update(lson, l, mid, ul, ur, val);
update(rson, mid+, r, ul, ur, val);
for (int i = ; i < ; i++)
pushUp(root, l, r, i);
} int query(int root, int l, int r, int qlen, int nu)
{
if (l == r) return l;
pushDown(root, l, r);
int mid = (l+r) >> ;
if (sum[nu][lson] >= qlen) return query(lson, l, mid, qlen, nu);
else if (rsum[nu][lson] + lsum[nu][rson] >= qlen) return mid - rsum[nu][lson] + ;
else return query(rson, mid+, r, qlen, nu);
}
int main()
{
//注意都是英文符号
//freopen("in.txt", "r", stdin);
int T;
scanf("%d", &T);
for (int cas = ; cas <= T; cas++)
{
printf("Case %d:\n", cas);
scanf("%d%d", &n, &m);
build(, , n);
for (int i = ; i < m; i++)
{
char buf[];
int qlen;
scanf("%s", buf);
if (buf[] == 'D')
{
scanf("%d", &qlen);
int pos = -;
if (qlen > n || sum[][] < qlen)
{
puts("fly with yourself");
continue;
}
pos = query(, , n, qlen, );
printf("%d,let's fly\n", pos);
update(, , n, pos, pos+qlen-, );
}
else if (buf[] == 'N')
{
scanf("%d", &qlen);
int pos = -;
if (qlen > n || sum[][] < qlen)
{
puts("wait for me");
continue;
}
if (sum[][] >= qlen) pos = query(, , n, qlen, );
else pos = query(, , n, qlen, );
printf("%d,don't put my gezi\n", pos);
update(, , n, pos, pos+qlen-, );
}
else
{
int l, r;
scanf("%d%d", &l, &r);
update(, , n, l, r, );
puts("I am the hope of chinese chengxuyuan!!");
}
}
}
return ;
}

区间合并 POJ3667+HDU4553的更多相关文章

  1. poj3667 Hotel (线段树 区间合并)

    poj3667 HotelTime Limit: 3000MS Memory Limit: 65536KTotal Submissions: 18925 Accepted: 8242Descripti ...

  2. poj3667 线段树 区间合并

    //Accepted 3728 KB 1079 ms //线段树 区间合并 #include <cstdio> #include <cstring> #include < ...

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

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

  4. poj3667(线段树区间合并&区间查询)

    题目链接: http://poj.org/problem?id=3667 题意:第一行输入 n, m表示有 n 间房间(连成一排的), 接下来有 m 行输入, 对于接下来的 m 行输入: 1 x : ...

  5. HDU - 4553 约会安排(区间合并)

    https://cn.vjudge.net/problem/HDU-4553 Description 寒假来了,又到了小明和女神们约会的季节.  小明虽为屌丝级码农,但非常活跃,女神们常常在小明网上的 ...

  6. POJ 3667 Hotel(线段树 区间合并)

    Hotel 转载自:http://www.cnblogs.com/scau20110726/archive/2013/05/07/3065418.html [题目链接]Hotel [题目类型]线段树 ...

  7. HDU 3911 线段树区间合并、异或取反操作

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=3911 线段树区间合并的题目,解释一下代码中声明数组的作用: m1是区间内连续1的最长长度,m0是区间内连续 ...

  8. HDU 1540 Tunnel Warfare 平衡树 / 线段树:单点更新,区间合并

    Tunnel Warfare                                  Time Limit: 4000/2000 MS (Java/Others)    Memory Lim ...

  9. HDU 3911 Black And White(线段树区间合并+lazy操作)

    开始以为是水题,结果...... 给你一些只有两种颜色的石头,0为白色,1为黑色. 然后两个操作: 1 l r 将[ l , r ]内的颜色取反 0 l r 计算[ l , r ]内最长连续黑色石头的 ...

随机推荐

  1. FZOJβ #31.字符串

    http://1572m36l09.iask.in:30808/problem/31 首先转化为保留尽量少的段使得字典序最大.考虑逐字符确定,显然我们可以将相同的连续字符缩在一起.注意到字典序最大的字 ...

  2. Java String Integer转换 练习:编程求字符串“100”和“150”按十进制数值做差后的结果以字符串形式输出。

    package com.swift; public class String_To_Integer_Test { public static void main(String[] args) { /* ...

  3. token_get_all()函数

    token_get_all (PHP 4 >= 4.2.0, PHP 5) token_get_all — 将提供的源码按 PHP 标记进行分割,可以用作php源代码的压缩,会按照固定的分解方法 ...

  4. C语言中sizeof的用法

    今天同学问我sizeof可不可以计算结构体的大小,我竟然忘了C语言还有sizeof这个函数,我是多久没有写程序了啊!!!惭愧,上研究生后写嵌入式方面的程序就特别少了,看来以后还要经常来练练手才行.现在 ...

  5. DeepFaceLab小白入门(6):脸部替换以及合成视频!

    前面的都是准备工作,这个环节才是真的换脸.换脸主要分两部分,1,图片换脸,2,把图片合成视频. 7) convert H64 debug.bat 这个环节是和训练环节相对于的,比如我们之前选的是H64 ...

  6. python 程序小测试

    python 程序小测试 对之前写的程序做简单的小测试 ... # -*- encoding:utf-8 -*- ''' 对所写程序做简单的测试 @author: bpf ''' def GameOv ...

  7. GoF23种设计模式之行为型模式之状态模式

    一.概述         定义对象之间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新. 二.适用性 1.一个对象的行为取决于它的状态,并且它必须在运行时刻 ...

  8. 使用selenium和phantomJS浏览器登陆豆瓣的小演示

    # 使用selenium和phantomJS浏览器登陆豆瓣的小演示 # 导入库 from selenium import webdriver # 实例化一个浏览器对象 web = webdriver. ...

  9. Applied Nonparametric Statistics-lec3

    Ref: https://onlinecourses.science.psu.edu/stat464/print/book/export/html/4 使用非参数方法的优势: 1. 对总体分布做的假设 ...

  10. aoj-0118 property distribution(搜索)

    Time limit1000 ms Memory limit131072 kB タナカ氏が HW アールの果樹園を残して亡くなりました.果樹園は東西南北方向に H × Wの区画に分けられ.区画ごとにリ ...