HLG 1524 最大 (离散化线段树)
2014-06-05 18:20
162 查看
链接: http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=1524
Description
给包含n个数的初始序列,A[1], A[2], ..., A
。
给q多个操作,操作如下:
1 a b v, 把[a, b] 的值改为v,即A[a] = A[a+1] = ... = A = v。
2 a b, 查询[a, b] 之间的相同数的连续和最大值。
在[a, b]区间内,相同数的连续和最大值就是Sum(A[i], A[i+1], A[j]), a <= i <= j <= b,并且A[i] = A[i+1] = A[i+2] = A[i+3] = ... = A[j]。
[b]Input
有多组测试数据,不超过5组测试数据。
对于每组测试数据,第一个为 n (n<=10^5),第二行为n个数,每个数的范围[0, 1000]。
第三行为 q (q<=10^5),表示查询的次数。
接下来有q个操作,格式如下:
1 a b v, 把[a, b] 的值改为v,即A[a] = A[a+1] = ... = A = v。
2 a b, 查询[a, b] 之间的相同数的连续和最大值。
其中 1 <= a <= b <=n,0 <= v <= 1000.
[b]Output
每组测试数据先输出一行"Case id:",id从1开始计数。
对于每个查询,输出一行,包含一个整数,为相同数的连续和最大值。
Sample Input
5
2 2 1 2 3
3
2 1 4
1 1 3 2
2 1 5
7
120 985 727 979 68 558 732
4
1 2 5 627
2 2 7
2 4 5
1 5 7 571
Sample Output
Case 1:
4
8
Case 2:
2508
1254
代码如下: (这代码当时把我弄疯了)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <limits.h>
#include <algorithm>
#define maxn 100005
#define RST(N)memset(N, 0, sizeof(N))
using namespace std;
int max(int a, int b) { return a > b ? a : b; }
int min(int a, int b) { return a < b ? a : b; }
int lva[maxn<<4]; // 最左面的值
int lnu[maxn<<4]; // 最左面的数的个数
int rva[maxn<<4]; // 最右面的值
int rnu[maxn<<4]; // 最右面的数的个数
int mva[maxn<<4]; // 区间最大连续值
int add[maxn<<4]; // 延迟标记
int v[maxn], re[100005];
void creat(int l, int r, int rt)
{
add[rt] = -1;
if(l == r) {
lva[rt] = rva[rt] = v[l];
lnu[rt] = rnu[rt] = 1;
mva[rt] = v[l];
return;
}
int m = (l+r) >> 1;
creat(l, m, rt<<1);
creat(m+1, r, rt<<1|1);
lva[rt] = lva[rt<<1];
lnu[rt] = lnu[rt<<1];
rva[rt] = rva[rt<<1|1];
rnu[rt] = rnu[rt<<1|1];
if(lva[rt<<1]==lva[rt<<1|1] && lnu[rt<<1]==(m-l+1)) lnu[rt] += lnu[rt<<1|1];
if(rva[rt<<1]==rva[rt<<1|1] && rnu[rt<<1|1]==r-m) rnu[rt] += rnu[rt<<1];
mva[rt] = max(mva[rt<<1], mva[rt<<1|1]);
if(rva[rt<<1] == lva[rt<<1|1]) {
mva[rt] = max(mva[rt], rva[rt<<1]*rnu[rt<<1]+lva[rt<<1|1]*lnu[rt<<1|1]);
}
}
void update(int L, int R, int c, int l, int r, int rt)
{
if(L <= l && r <= R) {
add[rt] = c;
lva[rt] = rva[rt] = c;
lnu[rt] = rnu[rt] = r-l+1;
mva[rt] = c*(r-l+1);
return;
}
int m = (l+r) >> 1;
if(add[rt] != -1) {
add[rt<<1] = add[rt<<1|1] = add[rt];
lva[rt<<1] = rva[rt<<1] = lva[rt<<1|1] = rva[rt<<1|1] = add[rt];
lnu[rt<<1] = rnu[rt<<1] = m-l+1;
lnu[rt<<1|1] = rnu[rt<<1|1] = r - m;
mva[rt<<1] = (m-l+1) * add[rt];
mva[rt<<1|1] = (r-m) * add[rt];
add[rt] = -1;
}
if(L <= m) update(L, R, c, l, m, rt<<1);
if(R > m) update(L, R, c, m+1, r, rt<<1|1);
lva[rt] = lva[rt<<1];
lnu[rt] = lnu[rt<<1];
rva[rt] = rva[rt<<1|1];
rnu[rt] = rnu[rt<<1|1];
if(lva[rt<<1] == lva[rt<<1|1] && lnu[rt<<1] == (m-l+1)) lnu[rt] += lnu[rt<<1|1];
if(rva[rt<<1] == rva[rt<<1|1]&& rnu[rt<<1|1] == r-m) rnu[rt] += rnu[rt<<1];
mva[rt] = max(mva[rt<<1], mva[rt<<1|1]);
if(rva[rt<<1] == lva[rt<<1|1]) {
mva[rt] = max(mva[rt], rva[rt<<1]*rnu[rt<<1]+lva[rt<<1|1]*lnu[rt<<1|1]);
}
}
int query(int L, int R, int l, int r, int rt)
{
if(L <= l && r <= R) return mva[rt];
int m = (l+r) >> 1;
if(add[rt] != -1) {
add[rt<<1] = add[rt<<1|1] = add[rt];
lva[rt<<1] = rva[rt<<1] = lva[rt<<1|1] = rva[rt<<1|1] = add[rt];
lnu[rt<<1] = rnu[rt<<1] = m-l+1;
lnu[rt<<1|1] = rnu[rt<<1|1] = r - m;
mva[rt<<1] = (m-l+1) * add[rt];
mva[rt<<1|1] = (r-m) * add[rt];
add[rt] = -1;
}
if(R <= m) return query(L, R, l, m, rt<<1);
else if(L > m) return query(L, R, m+1, r, rt<<1|1);
else {
int res = 0;
if(rva[rt<<1] == lva[rt<<1|1])
res = (min(rnu[rt<<1], m-L+1) + min(lnu[rt<<1|1], R-m)) * rva[rt<<1];
return max(res, max(query(L, m, l, m, rt<<1), query(m+1, R, m+1, r, rt<<1|1)));
}
}
int n, a, b, c, m, op, cas = 1, top = 0, tot;
void Init()
{
for(int i=1; i<=n; i++) scanf("%d", &v[i]);
creat(1, n, 1);
scanf("%d", &m);
tot = 0;
}
int main()
{
while(~scanf("%d", &n)) {
Init();
printf("Case %d:\n", cas++);
while(m--) {
scanf("%d", &op);
if(op == 1) {
scanf("%d %d %d", &a, &b, &c);
update(a, b, c, 1, n, 1);
}else {
scanf("%d %d", &a, &b);
printf("%d\n", query(a, b, 1, n, 1));
}
}
}
return 0;
}
Description
给包含n个数的初始序列,A[1], A[2], ..., A
。
给q多个操作,操作如下:
1 a b v, 把[a, b] 的值改为v,即A[a] = A[a+1] = ... = A = v。
2 a b, 查询[a, b] 之间的相同数的连续和最大值。
在[a, b]区间内,相同数的连续和最大值就是Sum(A[i], A[i+1], A[j]), a <= i <= j <= b,并且A[i] = A[i+1] = A[i+2] = A[i+3] = ... = A[j]。
[b]Input
有多组测试数据,不超过5组测试数据。
对于每组测试数据,第一个为 n (n<=10^5),第二行为n个数,每个数的范围[0, 1000]。
第三行为 q (q<=10^5),表示查询的次数。
接下来有q个操作,格式如下:
1 a b v, 把[a, b] 的值改为v,即A[a] = A[a+1] = ... = A = v。
2 a b, 查询[a, b] 之间的相同数的连续和最大值。
其中 1 <= a <= b <=n,0 <= v <= 1000.
[b]Output
每组测试数据先输出一行"Case id:",id从1开始计数。
对于每个查询,输出一行,包含一个整数,为相同数的连续和最大值。
Sample Input
5
2 2 1 2 3
3
2 1 4
1 1 3 2
2 1 5
7
120 985 727 979 68 558 732
4
1 2 5 627
2 2 7
2 4 5
1 5 7 571
Sample Output
Case 1:
4
8
Case 2:
2508
1254
代码如下: (这代码当时把我弄疯了)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <limits.h>
#include <algorithm>
#define maxn 100005
#define RST(N)memset(N, 0, sizeof(N))
using namespace std;
int max(int a, int b) { return a > b ? a : b; }
int min(int a, int b) { return a < b ? a : b; }
int lva[maxn<<4]; // 最左面的值
int lnu[maxn<<4]; // 最左面的数的个数
int rva[maxn<<4]; // 最右面的值
int rnu[maxn<<4]; // 最右面的数的个数
int mva[maxn<<4]; // 区间最大连续值
int add[maxn<<4]; // 延迟标记
int v[maxn], re[100005];
void creat(int l, int r, int rt)
{
add[rt] = -1;
if(l == r) {
lva[rt] = rva[rt] = v[l];
lnu[rt] = rnu[rt] = 1;
mva[rt] = v[l];
return;
}
int m = (l+r) >> 1;
creat(l, m, rt<<1);
creat(m+1, r, rt<<1|1);
lva[rt] = lva[rt<<1];
lnu[rt] = lnu[rt<<1];
rva[rt] = rva[rt<<1|1];
rnu[rt] = rnu[rt<<1|1];
if(lva[rt<<1]==lva[rt<<1|1] && lnu[rt<<1]==(m-l+1)) lnu[rt] += lnu[rt<<1|1];
if(rva[rt<<1]==rva[rt<<1|1] && rnu[rt<<1|1]==r-m) rnu[rt] += rnu[rt<<1];
mva[rt] = max(mva[rt<<1], mva[rt<<1|1]);
if(rva[rt<<1] == lva[rt<<1|1]) {
mva[rt] = max(mva[rt], rva[rt<<1]*rnu[rt<<1]+lva[rt<<1|1]*lnu[rt<<1|1]);
}
}
void update(int L, int R, int c, int l, int r, int rt)
{
if(L <= l && r <= R) {
add[rt] = c;
lva[rt] = rva[rt] = c;
lnu[rt] = rnu[rt] = r-l+1;
mva[rt] = c*(r-l+1);
return;
}
int m = (l+r) >> 1;
if(add[rt] != -1) {
add[rt<<1] = add[rt<<1|1] = add[rt];
lva[rt<<1] = rva[rt<<1] = lva[rt<<1|1] = rva[rt<<1|1] = add[rt];
lnu[rt<<1] = rnu[rt<<1] = m-l+1;
lnu[rt<<1|1] = rnu[rt<<1|1] = r - m;
mva[rt<<1] = (m-l+1) * add[rt];
mva[rt<<1|1] = (r-m) * add[rt];
add[rt] = -1;
}
if(L <= m) update(L, R, c, l, m, rt<<1);
if(R > m) update(L, R, c, m+1, r, rt<<1|1);
lva[rt] = lva[rt<<1];
lnu[rt] = lnu[rt<<1];
rva[rt] = rva[rt<<1|1];
rnu[rt] = rnu[rt<<1|1];
if(lva[rt<<1] == lva[rt<<1|1] && lnu[rt<<1] == (m-l+1)) lnu[rt] += lnu[rt<<1|1];
if(rva[rt<<1] == rva[rt<<1|1]&& rnu[rt<<1|1] == r-m) rnu[rt] += rnu[rt<<1];
mva[rt] = max(mva[rt<<1], mva[rt<<1|1]);
if(rva[rt<<1] == lva[rt<<1|1]) {
mva[rt] = max(mva[rt], rva[rt<<1]*rnu[rt<<1]+lva[rt<<1|1]*lnu[rt<<1|1]);
}
}
int query(int L, int R, int l, int r, int rt)
{
if(L <= l && r <= R) return mva[rt];
int m = (l+r) >> 1;
if(add[rt] != -1) {
add[rt<<1] = add[rt<<1|1] = add[rt];
lva[rt<<1] = rva[rt<<1] = lva[rt<<1|1] = rva[rt<<1|1] = add[rt];
lnu[rt<<1] = rnu[rt<<1] = m-l+1;
lnu[rt<<1|1] = rnu[rt<<1|1] = r - m;
mva[rt<<1] = (m-l+1) * add[rt];
mva[rt<<1|1] = (r-m) * add[rt];
add[rt] = -1;
}
if(R <= m) return query(L, R, l, m, rt<<1);
else if(L > m) return query(L, R, m+1, r, rt<<1|1);
else {
int res = 0;
if(rva[rt<<1] == lva[rt<<1|1])
res = (min(rnu[rt<<1], m-L+1) + min(lnu[rt<<1|1], R-m)) * rva[rt<<1];
return max(res, max(query(L, m, l, m, rt<<1), query(m+1, R, m+1, r, rt<<1|1)));
}
}
int n, a, b, c, m, op, cas = 1, top = 0, tot;
void Init()
{
for(int i=1; i<=n; i++) scanf("%d", &v[i]);
creat(1, n, 1);
scanf("%d", &m);
tot = 0;
}
int main()
{
while(~scanf("%d", &n)) {
Init();
printf("Case %d:\n", cas++);
while(m--) {
scanf("%d", &op);
if(op == 1) {
scanf("%d %d %d", &a, &b, &c);
update(a, b, c, 1, n, 1);
}else {
scanf("%d %d", &a, &b);
printf("%d\n", query(a, b, 1, n, 1));
}
}
}
return 0;
}
相关文章推荐
- HLG 1524 最大
- ZOJ 2301 / HDU 1199 Color the Ball 离散化+线段树区间连续最大和
- ZOJ 2301 / HDU 1199 Color the Ball 离散化+线段树区间连续最大和
- Codeforces Gym 100733J Summer Wars 线段树,区间更新,区间求最大值,离散化,区间求并
- HLG 2163 方格取数 (最大网络流)
- poj 2528 Mayor's posters(线段树+离散化)
- Hash 线段树离散化
- codeforces #261 D题 Pashmak and Parmida's problem(线段树+离散化)
- nyoj 1185 最大最小值【线段树最大值最小值维护】
- (重温)poj 2528 Mayor's posters 线段树 染色+离散化
- 哈理工OJ1524-最大
- HDU 1540 Tunnel Warfare(线段树,去最大连续区间)
- hdoj 5443 The Water Problem【线段树求区间最大值】
- hrbust 1524 最大(区间合并)
- NYOJ 117 求逆序数(离散化+线段树)
- 线段树、扫描线、离散化求面积并(hdu1542)
- HDU 1542 Atlantis (线段树 + 扫描线 + 离散化)
- BZOJ_1012_[JSOI2008]最大数maxnumber_暴力?(线段树)
- bzoj 1012 最大数 线段树 || 分块
- hdu 2528(离散化线段树)