HDU6638 2019 Multi - schools, sixth Snowy Smile (+ coordinate discrete segment tree enumeration maintenance intervals and the largest sub-segment)

The meaning of problems

T group, a n, line n below a given horizontal and vertical coordinates of the n points and this value (positive or negative), up to 2000 points, the range of coordinates (-1e9 ~ 1e9) ask you a block in FIG. the maximum value of a rectangle (inclusive) get is how much output MaxValue.

Thinking

Because the coordinate range is given -1e9 ~ 1e9, ordinate all discretization points, and then all the points in ascending order according to the abscissa, the enumeration of discrete points n, each time a different x-coordinate of the next encounter when (the rectangle in the left boundary modification), re-build segment tree (discrete step on here that different from the y-coordinate how many - how many points to be built), then the current left margin expanding rectangle right border, for each point on the right of the current line segment tree all pressed, and the segment tree maintenance, MaxValue maximum within the rectangular section each sub-segment maintenance. Ok, look at how discrete the largest sub-segment as well as maintenance and ...... ^ _ ^

Discrete coordinates

Put a big pile of coordinates into the gap adjacent QAQ nothing to say this is the discrete ordinates code

int m = 0,M = 0;
scanf("%d",&n);
for(int i = 1;i <= n; i++){
	scanf("%d %d %d",&a[i].x,&a[i].y,&a[i].w);
	b[++m] = a[i].y;
}
sort(b + 1,b + 1 + m);
for(int i = 1,M = 0;i <= m; i++){
	if(i == 1 || b[i] != b[M]) b[++M] = b[i];
}
sort(a + 1,a + 1 + n,cmp);//横坐标从小到大
for(int i = 1;i <= n; i++){
	a[i].y = lower_bound(b + 1,b + 1 + M,a[i].y) - b;
}

Segment tree maintenance intervals and the largest sub-segment

The largest sub-segment and the need to maintain these elements (っ • ω •) っ ✎⁾⁾ 

s-- intervals and

The largest sub-segment of the left half and the interval ls--

The largest sub-segment rs-- section and the right half

as-- range and largest sub-segment

During the maintenance, the following conversion:

s-- s is summed myself hahaha (¯.¯);

ls - max (left son of ls, left his son .s + Right son .ls);

rs - max (Right sons rs, left and right son .s + son .rs);

as - max (the right son of the left son .rs + .ls, max (the right son of the left son .as ,. AS));

Do not understand, then draw a diagram on ok friends (<ゝ ω ·) ☆

the complexity

Coordinate discretization O (n) Maintenance O (n ^ 2 log n)

Code implementation (· ω <)

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>

using namespace std;
const int MaxN = 2005;
typedef long long LL;

int t,n;
int b[MaxN];
LL ans;

struct NODE{
	int x,y,w;
}a[MaxN];

struct NN{
	LL s,ls,rs,as,l,r;
}tree[MaxN * 4];

bool cmp(NODE A,NODE B){
	return A.x < B.x;
}

void build(int k,int ll,int rr){
	tree[k].s = tree[k].ls = tree[k].rs = tree[k].as = 0;
	tree[k].l = ll;
	tree[k].r = rr;
	if(ll == rr) return;
	int mid = (ll + rr) / 2;
	build(k * 2,ll,mid);
	build(k * 2 + 1,mid + 1,rr);
}

void push_up(int k){
	tree[k].s = tree[k * 2].s + tree[k * 2 + 1].s;
	tree[k].ls = max(tree[k * 2].ls,tree[k * 2 + 1].ls + tree[k * 2].s);
	tree[k].rs = max(tree[k * 2 + 1].rs,tree[k * 2].rs + tree[k * 2 + 1].s);
	tree[k].as = max(tree[k * 2].rs + tree[k * 2 + 1].ls,max(tree[k * 2].as,tree[k * 2 + 1].as));
}

void chan_p(int k,int pos,int ad){
	if(tree[k].l == tree[k].r){
		tree[k].s += ad;
		tree[k].ls += ad;
		tree[k].rs += ad;
		tree[k].as += ad;
		return ;
	}
	int mid = (tree[k].l + tree[k].r) / 2;
	if(pos <= mid) chan_p(2 * k,pos,ad);
	else chan_p(2 * k + 1,pos,ad);
	push_up(k);//向上反馈哦~
}

int main()
{
	scanf("%d",&t);
	while(t--){
		int M = 0;
		scanf("%d",&n);
		for(int i = 1;i <= n; i++){
			scanf("%d %d %d",&a[i].x,&a[i].y,&a[i].w);
			b[i] = a[i].y;
		}
		sort(b + 1,b + 1 + n);
		for(int i = 1;i <= n; i++){
			if(i == 1 || b[i] != b[M]) b[++M] = b[i];
		}
		sort(a + 1,a + 1 + n,cmp);//横坐标从小到大
		for(int i = 1;i <= n; i++){
			a[i].y = lower_bound(b + 1,b + 1 + M,a[i].y) - b;
		}
		ans = 0;
		int k = 0;

		for(int i = 1;i <= n; i++){
			if(i == 1 || a[i].x != a[i - 1].x){//左边界修改
				build(1,1,M);//M个不同纵坐标 清空
				for(int j = i;j <= n; j = k){
					for(k = j;k <= n && a[j].x == a[k].x; k++){
						//扩展的右边界上的所有点压入线段树
						chan_p(1,a[k].y,a[k].w);
					}
					ans = max(ans,tree[1].as);
				}
			}
		}
		printf("%lld\n",ans);
	}
}

 

Published 31 original articles · won praise 5 · Views 1381

Guess you like

Origin blog.csdn.net/qq_43685900/article/details/98954221