区间合并 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 ]内最长连续黑色石头的 ...
随机推荐
- Bootstrap 提示工具(Tooltip)插件方法的用法
方法 下面是一些提示工具(Tooltip)插件中有用的方法: 方法 描述 实例 Options: .tooltip(options) 向元素集合附加提示工具句柄. $().tooltip(option ...
- 【思维题 集合hash 树上差分】11.5撸树
要注重问题的转化和一些结论的推断 题目描述 要致富,先撸树. 一棵树的形状可以简化为一张 $N$ 个点 $M$ 条边的图,由于装备条件限制,你只有撸两次,也就是删去两条边,当这张图不联通时,就意味着树 ...
- 【状态压缩dp】1195: [HNOI2006]最短母串
一个清晰的思路就是状压dp:不过也有AC自动机+BFS的做法 Description 给定n个字符串(S1,S2,„,Sn),要求找到一个最短的字符串T,使得这n个字符串(S1,S2,„,Sn)都是T ...
- 面试:如何把xxx.sh使用/etc/init.d/xxx.sh start启动,并且可以用chkconfig配置开机自启动
chkconfig原理: 1.脚本放到/etc/init.d下面,并且可执行(/etc/init.d/sshd) 需要被chkconfig管理,需要添加进去chkconfig --add sshd ...
- linux三剑客正则表达式
^:以...开头,^d,意思是以d开头.例如:ls -F(-p) | grep " ^d " $:以...结尾,/$,意思是以/结尾.例如:ls -F(-p) | grep &q ...
- 转载:将画布(canvas)图像保存成本地图片的方法
之前我曾介绍过如何将HTML5画布(canvas)内容转变成图片形式,方法十分简单.但后来我发现只将canvas内容转变成图片输出还不够,如何能将转变后的图片保存到本地呢? 其实,这个方法也是非常简单 ...
- 【android】【android studio】修改emulator的本地化环境
Changing the emulator locale from the adb shell To change the locale in the emulator by using the ad ...
- 谷歌放弃“不作恶” Alphabet要“遵守法律互相尊重”
对于一些谷歌粉而言,谷歌那条“不作恶(Don’t be evil)”的行为准则是他们引以为傲的精神信仰.这一准则于1999年被首次确认,谷歌在2004年申请上市时也提到了这一点.不过现在这一点要改变了 ...
- OOP中常用到的函数
学习地址: http://www.jikexueyuan.com/course/2420.html 判断类是否存在 class_exists() 得到类或者对象中的成员方法组成的数组 get_clas ...
- LeetCode(224) Basic Calculator
题目 Implement a basic calculator to evaluate a simple expression string. The expression string may co ...