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

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. Bootstrap 提示工具(Tooltip)插件方法的用法

    方法 下面是一些提示工具(Tooltip)插件中有用的方法: 方法 描述 实例 Options: .tooltip(options) 向元素集合附加提示工具句柄. $().tooltip(option ...

  2. 【思维题 集合hash 树上差分】11.5撸树

    要注重问题的转化和一些结论的推断 题目描述 要致富,先撸树. 一棵树的形状可以简化为一张 $N$ 个点 $M$ 条边的图,由于装备条件限制,你只有撸两次,也就是删去两条边,当这张图不联通时,就意味着树 ...

  3. 【状态压缩dp】1195: [HNOI2006]最短母串

    一个清晰的思路就是状压dp:不过也有AC自动机+BFS的做法 Description 给定n个字符串(S1,S2,„,Sn),要求找到一个最短的字符串T,使得这n个字符串(S1,S2,„,Sn)都是T ...

  4. 面试:如何把xxx.sh使用/etc/init.d/xxx.sh start启动,并且可以用chkconfig配置开机自启动

    chkconfig原理: 1.脚本放到/etc/init.d下面,并且可执行(/etc/init.d/sshd) 需要被chkconfig管理,需要添加进去chkconfig  --add  sshd ...

  5. linux三剑客正则表达式

    ^:以...开头,^d,意思是以d开头.例如:ls  -F(-p) | grep " ^d " $:以...结尾,/$,意思是以/结尾.例如:ls -F(-p) | grep &q ...

  6. 转载:将画布(canvas)图像保存成本地图片的方法

    之前我曾介绍过如何将HTML5画布(canvas)内容转变成图片形式,方法十分简单.但后来我发现只将canvas内容转变成图片输出还不够,如何能将转变后的图片保存到本地呢? 其实,这个方法也是非常简单 ...

  7. 【android】【android studio】修改emulator的本地化环境

    Changing the emulator locale from the adb shell To change the locale in the emulator by using the ad ...

  8. 谷歌放弃“不作恶” Alphabet要“遵守法律互相尊重”

    对于一些谷歌粉而言,谷歌那条“不作恶(Don’t be evil)”的行为准则是他们引以为傲的精神信仰.这一准则于1999年被首次确认,谷歌在2004年申请上市时也提到了这一点.不过现在这一点要改变了 ...

  9. OOP中常用到的函数

    学习地址: http://www.jikexueyuan.com/course/2420.html 判断类是否存在 class_exists() 得到类或者对象中的成员方法组成的数组 get_clas ...

  10. LeetCode(224) Basic Calculator

    题目 Implement a basic calculator to evaluate a simple expression string. The expression string may co ...