Snowy Smile HDU - 6638(扫描线,线段树区间合并)

2024-04-15 23:38

本文主要是介绍Snowy Smile HDU - 6638(扫描线,线段树区间合并),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

There are n pirate chests buried in Byteland, labeled by 1,2,…,n. The i-th chest’s location is (xi,yi), and its value is wi, wi can be negative since the pirate can add some poisonous gases into the chest. When you open the i-th pirate chest, you will get wi value.

You want to make money from these pirate chests. You can select a rectangle, the sides of which are all paralleled to the axes, and then all the chests inside it or on its border will be opened. Note that you must open all the chests within that range regardless of their values are positive or negative. But you can choose a rectangle with nothing in it to get a zero sum.

Please write a program to find the best rectangle with maximum total value.
Input
The first line of the input contains an integer T(1≤T≤100), denoting the number of test cases.

In each test case, there is one integer n(1≤n≤2000) in the first line, denoting the number of pirate chests.

For the next n lines, each line contains three integers xi,yi,wi(−109≤xi,yi,wi≤109), denoting each pirate chest.

It is guaranteed that ∑n≤10000.
Output
For each test case, print a single line containing an integer, denoting the maximum total value.
Sample Input
2
4
1 1 50
2 1 50
1 2 50
2 2 -500
2
-1 1 5
-1 1 1
Sample Output
100
6

题意:
平面上很多个带权点,求一个矩阵覆盖一些点使得权值和最大。

思路:
n n n的范围只有2000,所以可以枚举矩阵的下边界( y y y轴)。然后每次将矩阵上边界移动一个单位(离散化后的单位)。线段树维护每个点在 x x x轴上的位置,维护一下最大值,就得到了当前的最大权值矩阵。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <iostream>using namespace std;typedef long long ll;
const int maxn = 4e3 + 7;
struct Node {int x,y,w;
}a[maxn];
vector<pair<int,int> >vec[maxn];struct Tree {int l,r;ll sum;ll mx,lmx,rmx;
}t[maxn << 2];void pushup(int i) {t[i].mx = max(max(t[i * 2].mx,t[i * 2 + 1].mx),t[i * 2].rmx + t[i * 2 + 1].lmx);t[i].sum = t[i * 2].sum + t[i * 2 + 1].sum;t[i].lmx = max(t[i * 2].lmx,t[i * 2].sum + t[i * 2 + 1].lmx);t[i].rmx = max(t[i * 2 + 1].rmx,t[i * 2 + 1].sum + t[i * 2].rmx);
}void build(int i,int l,int r) {t[i].l = l;t[i].r = r;if(l == r) {t[i].sum = t[i].mx = t[i].lmx = t[i].rmx = 0;return;}int m = (l + r) >> 1;build(i * 2,l,m);build(i * 2 + 1,m + 1,r);pushup(i);
}void update(int i,int x,int v) {if(t[i].l == t[i].r) {t[i].sum += v;t[i].lmx += v;t[i].rmx += v;t[i].mx += v;return;}int m = (t[i].l + t[i].r) >> 1;if(x <= m) update(i * 2,x,v);if(x > m)  update(i * 2 + 1,x,v);pushup(i);
}int main() {int T;scanf("%d",&T);while(T--) {int n;scanf("%d",&n);vector<int>vecx,vecy;for(int i = 1;i <= n;i++) {scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].w);vecx.push_back(a[i].x);vecy.push_back(a[i].y);vec[i].clear();}sort(vecx.begin(),vecx.end());sort(vecy.begin(),vecy.end());vecx.erase(unique(vecx.begin(),vecx.end()),vecx.end());vecy.erase(unique(vecy.begin(),vecy.end()),vecy.end());for(int i = 1;i <= n;i++) {a[i].x = lower_bound(vecx.begin(),vecx.end(),a[i].x) - vecx.begin() + 1;a[i].y = lower_bound(vecy.begin(),vecy.end(),a[i].y) - vecy.begin() + 1;vec[a[i].y].push_back({a[i].x,a[i].w});}ll ans = 0;for(int i = 1;i <= vecy.size();i++) { //矩阵下界build(1,1,vecy.size());for(int j = i;j <= vecy.size();j++) { //矩阵上界for(int k = 0;k < vec[j].size();k++) {int pos = vec[j][k].first,val = vec[j][k].second;update(1,pos,val);}ans = max(ans,t[1].mx);}}printf("%lld\n",ans);}return 0;
}

这篇关于Snowy Smile HDU - 6638(扫描线,线段树区间合并)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/907245

相关文章

使用Python合并 Excel单元格指定行列或单元格范围

《使用Python合并Excel单元格指定行列或单元格范围》合并Excel单元格是Excel数据处理和表格设计中的一项常用操作,本文将介绍如何通过Python合并Excel中的指定行列或单... 目录python Excel库安装Python合并Excel 中的指定行Python合并Excel 中的指定列P

基于C#实现PDF文件合并工具

《基于C#实现PDF文件合并工具》这篇文章主要为大家详细介绍了如何基于C#实现一个简单的PDF文件合并工具,文中的示例代码简洁易懂,有需要的小伙伴可以跟随小编一起学习一下... 界面主要用于发票PDF文件的合并。经常出差要报销的很有用。代码using System;using System.Col

Python视频剪辑合并操作的实现示例

《Python视频剪辑合并操作的实现示例》很多人在创作视频时都需要进行剪辑,本文主要介绍了Python视频剪辑合并操作的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习... 目录介绍安装FFmpegWindowsMACOS安装MoviePy剪切视频合并视频转换视频结论介绍

不删数据还能合并磁盘? 让电脑C盘D盘合并并保留数据的技巧

《不删数据还能合并磁盘?让电脑C盘D盘合并并保留数据的技巧》在Windows操作系统中,合并C盘和D盘是一个相对复杂的任务,尤其是当你不希望删除其中的数据时,幸运的是,有几种方法可以实现这一目标且在... 在电脑生产时,制造商常为C盘分配较小的磁盘空间,以确保软件在运行过程中不会出现磁盘空间不足的问题。但在

在C#中合并和解析相对路径方式

《在C#中合并和解析相对路径方式》Path类提供了几个用于操作文件路径的静态方法,其中包括Combine方法和GetFullPath方法,Combine方法将两个路径合并在一起,但不会解析包含相对元素... 目录C#合并和解析相对路径System.IO.Path类幸运的是总结C#合并和解析相对路径对于 C

hdu2241(二分+合并数组)

题意:判断是否存在a+b+c = x,a,b,c分别属于集合A,B,C 如果用暴力会超时,所以这里用到了数组合并,将b,c数组合并成d,d数组存的是b,c数组元素的和,然后对d数组进行二分就可以了 代码如下(附注释): #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<que

poj3468(线段树成段更新模板题)

题意:包括两个操作:1、将[a.b]上的数字加上v;2、查询区间[a,b]上的和 下面的介绍是下解题思路: 首先介绍  lazy-tag思想:用一个变量记录每一个线段树节点的变化值,当这部分线段的一致性被破坏我们就将这个变化值传递给子区间,大大增加了线段树的效率。 比如现在需要对[a,b]区间值进行加c操作,那么就从根节点[1,n]开始调用update函数进行操作,如果刚好执行到一个子节点,

hdu1394(线段树点更新的应用)

题意:求一个序列经过一定的操作得到的序列的最小逆序数 这题会用到逆序数的一个性质,在0到n-1这些数字组成的乱序排列,将第一个数字A移到最后一位,得到的逆序数为res-a+(n-a-1) 知道上面的知识点后,可以用暴力来解 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#in

hdu1689(线段树成段更新)

两种操作:1、set区间[a,b]上数字为v;2、查询[ 1 , n ]上的sum 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<queue>#include<set>#include<map>#include<stdio.h>#include<stdl

usaco 1.3 Mixing Milk (结构体排序 qsort) and hdu 2020(sort)

到了这题学会了结构体排序 于是回去修改了 1.2 milking cows 的算法~ 结构体排序核心: 1.结构体定义 struct Milk{int price;int milks;}milk[5000]; 2.自定义的比较函数,若返回值为正,qsort 函数判定a>b ;为负,a<b;为0,a==b; int milkcmp(const void *va,c