2019杭电多校6 hdu6638 Snowy Smile(二维最大矩阵和 线段树)

http://acm.hdu.edu.cn/showproblem.php?pid=6638

题意:给你一些点的权值,让找一个矩形圈住一部分点,问圈住点的最大权值和

分析:由于是稀疏图,明显要先把x,y坐标离散化,暴力是n^3?(枚举边界n^2,求和是n)显然过不了,那可以枚举y的边界,然后对于x就是最大子段和的问题了,用线段树维护,n^2logn可以过。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn = 4e3+5;
 4 const int inf = 0x3f3f3f;
 5 typedef pair<int,int> P;
 6 typedef long long ll;
 7 int cas,n;
 8 struct point{
 9     int x,y,val;
10     bool operator<(const point &a) const{
11         return y<a.y;
12     }
13 }a[maxn];
14 vector<int> p[maxn];
15 int bx[maxn],by[maxn];
16 
17 struct node{
18     ll sum,lmax,rmax,lrmax;
19 }tree[maxn<<2];
20 
21 inline void pushup(int rt){
22     tree[rt].sum = tree[rt<<1].sum+tree[rt<<1|1].sum;
23     tree[rt].lmax = max(tree[rt<<1].lmax,tree[rt<<1].sum+tree[rt<<1|1].lmax);
24     tree[rt].rmax = max(tree[rt<<1|1].rmax,tree[rt<<1].rmax+tree[rt<<1|1].sum);
25     tree[rt].lrmax = max(max(tree[rt<<1].lrmax,tree[rt<<1|1].lrmax),tree[rt<<1].rmax+tree[rt<<1|1].lmax);
26 }
27 
28 inline void update(int L,int l,int r,int rt,int c){
29     if(l==r){
30         tree[rt].sum += 1ll*c;
31         tree[rt].lrmax = tree[rt].lmax = tree[rt].rmax = tree[rt].sum;
32         return;
33     }
34     int mid = l+r>>1;
35     if(L<=mid) update(L,l,mid,rt<<1,c);
36     else update(L,mid+1,r,rt<<1|1,c);
37     pushup(rt);
38 }
39 
40 int main(){
41     cin>>cas;
42     while(cas--){
43         cin>>n;
44         for(int i=1;i<=n;i++){
45             cin>>a[i].x>>a[i].y>>a[i].val;
46             bx[i] = a[i].x,by[i] = a[i].y;
47         }
48         sort(bx+1,bx+1+n);
49         int xlen = unique(bx+1,bx+1+n)-bx-1;
50         sort(by+1,by+1+n);
51         int ylen = unique(by+1,by+1+n)-by-1;
52         for(int i=1;i<=n;i++){
53             a[i].x = lower_bound(bx+1,bx+xlen+1,a[i].x)-bx;
54             a[i].y = lower_bound(by+1,by+ylen+1,a[i].y)-by;
55         }
56         sort(a+1,a+1+n);
57         ll ans = 0;
58         for(int i=1;i<=ylen;i++){
59             memset(tree,0,(xlen*4+5)*sizeof(node));
60             int pos = 1;
61             while(a[pos].y<i&&pos<=n) pos++;
62             for(int j=i;j<=ylen;j++){
63                 while(a[pos].y<=j&&pos<=n){
64                     update(a[pos].x,1,xlen,1,a[pos].val);
65                     pos++;
66                 }
67                 ans = max(ans,tree[1].lrmax);
68             }
69            
70         }
71         cout<<ans<<endl;
72     }
73     return 0;
74 }
View Code
原文地址:https://www.cnblogs.com/wzgg/p/11343013.html