区间合并 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 ]内最长连续黑色石头的 ...
随机推荐
- Linux Cache 机制探究
http://www.penglixun.com/tech/system/linux_cache_discovery.html
- Java获取yml里面的配置
#yml文件配置systemPath: #档案系统地址 dossier: http://127.0.0.1:8088/ //调用说明 配置文件里必须包含节点 否则项目无法启动 @Value(" ...
- java基础—基础语法2
一.语句
- Xcode开发技巧
1.Xcode 中的 Code Snippets 默认放在下面的目录中: ~/Library/Developer/Xcode/UserData/CodeSnippets 2.自定义的代码背景颜色和代码 ...
- 自然数的拆分(DFS)
题目描述: 任何一个大于1的自然数n,总可以拆分成若干个小于n的自然数之和. 输入格式: 待拆分的自然数n. 输出格式: 若干数的加法式子. 样例输入: 7 样例输出: 1+1+1+1+1+1+1 1 ...
- [提供可行性脚本] RHEL/CentOS 7 多节点SSH免密登陆
实验说明: 在自动化部署时,会经常SSH别的机器去操作,然而每次的密码认证却很令人烦躁,尤其是很长的密码,因此SSH免密登陆就显得必不可少: 在机器数目很多的时候,使用更过的往往是Ansible分发并 ...
- jquery.imgpreload.min.js插件实现页面图片预加载
页面分享地址: http://wenku.baidu.com/link?url=_-G8miwbgDmEj6miyFtjit1duJggBCJmFjR2jky_G1VftD9eS9kwGOlFWAOR ...
- DC 课程内容
- 使用laravel框架的eloquent\DB模型连接多个数据库
1.配置.env文件 DB_HOST_TRAILER=127.0.0.1DB_PORT_TRAILER=3306DB_DATABASE_TRAILER=htms_trailerDB_USERNAME_ ...
- 如何封装RESTful Web Service
所谓Web Service是一个平台独立的,低耦合的,自包含的.可编程的Web应用程序,有了Web Service异构系统之间就可以通过XML或JSON来交换数据,这样就可以用于开发分布式的互操作的应 ...