Spoj 1557 Can you answer these queries II 线段树 任意区间最大子段和 不重复数字

题目链接:点击打开链接

每个点都是最大值,把一整个序列和都压缩在一个点里。

#include <vector>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <stdio.h>
using namespace std;
#define N 100005
#define Lson(x) (x<<1)
#define Rson(x) (x<<1|1)
#define L(x) tree[x].l
#define R(x) tree[x].r
#define Old(x) tree[x].old
#define Sum(x) tree[x].sum
#define Lazy(x) tree[x].lazy
#define Olazy(x) tree[x].oldlazy
inline int Mid(int l, int r){return (l+r)>>1;}
struct Subtree{
	int l, r;
	int old, oldlazy, sum, lazy;
}tree[N<<2];
void push_down(int id){
	if(L(id) == R(id)) return ;
	if(Lazy(id) || Olazy(id)){
		Olazy(Lson(id)) = max(Olazy(Lson(id)), Lazy(Lson(id)) + Olazy(id));
		Old(Lson(id)) = max(Old(Lson(id)), Sum(Lson(id)) + Olazy(id));
		Lazy(Lson(id)) += Lazy(id); Sum(Lson(id)) += Lazy(id);

		Olazy(Rson(id)) = max(Olazy(Rson(id)), Lazy(Rson(id)) + Olazy(id));
		Old(Rson(id)) = max(Old(Rson(id)), Sum(Rson(id)) + Olazy(id));
		Lazy(Rson(id)) += Lazy(id); Sum(Rson(id)) += Lazy(id);
		Lazy(id) = Olazy(id) = 0;
	}
}
void push_up(int id){
	if(L(id) == R(id)) return ;
	Old(id) = max(Old(Lson(id)), Old(Rson(id)));
	Sum(id) = max(Sum(Lson(id)), Sum(Rson(id)));
}
void build(int l, int r, int id){
	L(id) = l; R(id) = r;
	Sum(id) = Old(id) = Lazy(id) = Olazy(id) = 0;
	if(l == r) return ;
	int mid = Mid(l, r);
	build(l, mid, Lson(id)); build(mid+1, r, Rson(id));
}
void updata(int l, int r, int val, int id){
	push_down(id);
	if(l == L(id) && R(id) == r) {
		Sum(id) += val;
		Lazy(id) += val;
		Olazy(id) = max(Olazy(id), Lazy(id));
		Old(id) = max(Old(id), Sum(id));
		return ;
	}
	int mid = Mid(L(id), R(id));
	if(mid < l)
		updata(l, r, val, Rson(id));
	else if(r <= mid)
		updata(l, r, val, Lson(id));
	else {
		updata(l, mid, val, Lson(id));
		updata(mid+1, r, val, Rson(id));
	}
	push_up(id);
}
int Query(int l, int r, int id){
	push_down(id);
	if(l == L(id) && R(id) == r) return Old(id);
	int ans , mid = Mid(L(id), R(id));
	if(mid < l)
		ans = Query(l, r, Rson(id));
	else if(r <= mid)
		ans = Query(l, r, Lson(id));
	else
		ans = max(Query(l, mid, Lson(id)), Query(mid+1, r, Rson(id)));
	push_up(id);
	return ans;
}
int a[N], n, las[N<<1];
struct node{
	int l, r, num, ans;
}query[N];
bool cmp1(node a, node b){return a.r < b.r;}
bool cmp2(node a, node b){return a.num < b.num;}
void solve(){
	int i, q;
	for(i = 1; i <= n; i++)scanf("%d",&a[i]);
	build(1, n, 1);
	scanf("%d",&q);
	for(i = 1; i <= q; i++)scanf("%d %d",&query[i].l, &query[i].r), query[i].num = i;
	sort(query+1, query+q+1, cmp1);
	int top = 1;
	memset(las, 0, sizeof las);
	for(i = 1; i <= n && top <= q; i++){
		updata(las[a[i]+N]+1, i, a[i], 1);
		las[a[i]+N] = i;
		while(query[top].r == i && top <= q){
			query[top].ans = Query(query[top].l, query[top].r, 1);
			top++;
		}
	}
	sort(query+1, query+q+1, cmp2);
	for(i = 1; i <= q; i++)printf("%d\n", query[i].ans);
}
int main(){
	while(~scanf("%d",&n))
		solve();
	return 0;
}
时间: 2024-10-17 03:05:43

Spoj 1557 Can you answer these queries II 线段树 任意区间最大子段和 不重复数字的相关文章

SPOJ 1557. Can you answer these queries II 线段树

Can you answer these queries II Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 https://www.spoj.com/problems/GSS2/ Description Being a completist and a simplist, kid Yang Zhe cannot solve but get Wrong Answer from most of the OI problems. And he refuse

bzoj 2482: [Spoj GSS2] Can you answer these queries II 线段树

2482: [Spoj1557] Can you answer these queries II Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 145  Solved: 76[Submit][Status][Discuss] Description 给定n个元素的序列. 给出m个询问:求l[i]~r[i]的最大子段和(可选空子段). 这个最大子段和有点特殊:一个数字在一段中出现了两次只算一次. 比如:1,2,3,2,2,2出现了3次,但只算一次,

SPOJ GSS3 Can you answer these queries III (线段树)

题目大意: 求区间最大子区间的和. 思路分析: 记录左最大,右最大,区间最大. 注意Q_L  和 Q_R  就好. #include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #define lson num<<1,s,mid #define rson num<<1|1,mid+1,e #define maxn 55555 using na

SPOJ GSS4 Can you answer these queries IV (线段树)

题目大意: 给出N个数 0     操作   把 l -----  r之间的数全部开平方 1     操作  输出 l -----r  之间的和 思路分析: 判断区间里的数字是否全相同.如果相同, 将cov 置为该数 查询的时候和更新的时候,如果碰到cov != -1 的  就直接返回就可以了 #include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #incl

【BZOJ2482】[Spoj1557] Can you answer these queries II 线段树

[BZOJ2482][Spoj1557] Can you answer these queries II Description 给定n个元素的序列. 给出m个询问:求l[i]~r[i]的最大子段和(可选空子段). 这个最大子段和有点特殊:一个数字在一段中出现了两次只算一次. 比如:1,2,3,2,2,2出现了3次,但只算一次,于是这个序列的和是1+2+3=6. Input 第一行一个数n. 第二行n个数,为给定的序列,这些数的绝对值小于等于100000. 第三行一个数m. 接下来m行,每行两个

HDOJ 题目4027 Can you answer these queries?(线段树,区间减为平方根,区间求和)

Can you answer these queries? Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others) Total Submission(s): 10057    Accepted Submission(s): 2305 Problem Description A lot of battleships of evil are arranged in a line befor

SPOJ GSS5 Can you answer these queries V ——线段树

[题目分析] GSS1上增加区间左右端点的限制. 直接分类讨论就好了. [代码] #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <map> #include <set> #include <queue> #include <string> #include <iostream> #i

SPOJ GSS3 Can you answer these queries III ——线段树

[题目分析] GSS1的基础上增加修改操作. 同理线段树即可,多写一个函数就好了. [代码] #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <map> #include <set> #include <queue> #include <string> #include <iostream&

Spoj 1716 Can you answer these queries III 线段树 单点修改 区间求最大子段和

题目链接:点击打开链接 == 原来写1的时候已经把更新函数写好了.. #include <cstdio> #include <iostream> #include <algorithm> #include <string.h> #include <math.h> #include <vector> #include <map> using namespace std; #define N 50050 #define Lso