区间合并 POJ3667+HDU4553
两道题都是线段树的区间合并
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的更多相关文章
- poj3667 Hotel (线段树 区间合并)
poj3667 HotelTime Limit: 3000MS Memory Limit: 65536KTotal Submissions: 18925 Accepted: 8242Descripti ...
- poj3667 线段树 区间合并
//Accepted 3728 KB 1079 ms //线段树 区间合并 #include <cstdio> #include <cstring> #include < ...
- poj-3667(线段树区间合并)
题目链接:传送门 参考文章:传送门 思路:线段树区间合并问题,每次查询到满足线段树的区间最左值,然后更新线段树. #include<iostream> #include<cstdio ...
- poj3667(线段树区间合并&区间查询)
题目链接: http://poj.org/problem?id=3667 题意:第一行输入 n, m表示有 n 间房间(连成一排的), 接下来有 m 行输入, 对于接下来的 m 行输入: 1 x : ...
- HDU - 4553 约会安排(区间合并)
https://cn.vjudge.net/problem/HDU-4553 Description 寒假来了,又到了小明和女神们约会的季节. 小明虽为屌丝级码农,但非常活跃,女神们常常在小明网上的 ...
- POJ 3667 Hotel(线段树 区间合并)
Hotel 转载自:http://www.cnblogs.com/scau20110726/archive/2013/05/07/3065418.html [题目链接]Hotel [题目类型]线段树 ...
- HDU 3911 线段树区间合并、异或取反操作
题目:http://acm.hdu.edu.cn/showproblem.php?pid=3911 线段树区间合并的题目,解释一下代码中声明数组的作用: m1是区间内连续1的最长长度,m0是区间内连续 ...
- HDU 1540 Tunnel Warfare 平衡树 / 线段树:单点更新,区间合并
Tunnel Warfare Time Limit: 4000/2000 MS (Java/Others) Memory Lim ...
- HDU 3911 Black And White(线段树区间合并+lazy操作)
开始以为是水题,结果...... 给你一些只有两种颜色的石头,0为白色,1为黑色. 然后两个操作: 1 l r 将[ l , r ]内的颜色取反 0 l r 计算[ l , r ]内最长连续黑色石头的 ...
随机推荐
- 从输入url到页面加载完成发生了什么详解
这是一道经典的面试题,这道题没有一个标准的答案,它涉及很多的知识点,面试官会通过这道题了解你对哪一方面的知识比较擅长,然后继续追问看看你的掌握程度.当然我写的这些也只是我的一些简单的理解,从前端的角度 ...
- java基础——随机数问题
/** * 要求:随机打印50个随机(4-10长度)的字符串,要求字符串包含的范围是所有的英文字母包含大小写和数字, * 按照编码顺序排序,每行打印4个,要求首字符对齐 * @author fanyu ...
- mysql锁机制(转载)
锁是计算机协调多个进程或线程并发访问某一资源的机制 .在数据库中,除传统的 计算资源(如CPU.RAM.I/O等)的争用以外,数据也是一种供许多用户共享的资源.如何保证数据并发访问的一致性.有效性是所 ...
- Python + Bottle + 谷歌搜索Api 实现简单搜索引擎
1.运行环境 python3 centos7 2.Bottle的使用 使用bottle主要是因为它仅用python自带的库即可实现对web的搭建. bottle源码分析 bottle使用教程 3.代码 ...
- MySQL中文转换成拼音的函数
CREATE DEFINER=`root`@`localhost` FUNCTION `fristPinyin`(`P_NAME` VARCHAR(255) CHARSET utf8) RETURNS ...
- Django 惰性机制
惰性机制:Publisher.objects.all()或者.filter()等都只是返回了一个QuerySet(查询结果集对象),它并不会马上执行sql,而是当调用QuerySet的时候才执行sql ...
- Java-downloadFileByLink
import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.ByteArrayOutputStr ...
- POJ:2060-Taxi Cab Scheme(最小路径覆盖)
传送门:http://poj.org/problem?id=2060 Taxi Cab Scheme Time Limit: 1000MS Memory Limit: 30000K Total Sub ...
- ACM训练联盟周赛 A. Teemo's bad day
65536K Today is a bad day. Teemo is scolded badly by his teacher because he didn't do his homework ...
- Linux学习-检验软件正确性
md5sum / sha1sum / sha256sum 目前有多种机制可以计算文件的指纹码,我们选择使用较为广泛的 MD5, SHA1 或 SHA256 加密机 制来处理,我们拿NTP 软件来检查看 ...