HDU 6638 Snowy Smile(线段树求二维最大连续子段和)

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

先离散化坐标,枚举上下边界,线段树维护区间最大连续字段和。

 1 #define bug(x) cout<<#x<<" is "< 2 #define IO std::ios::sync_with_stdio(0)
 3 #include 
 4 #define iter ::iterator
 5 #define pa pair
 6 using namespace  std;
 7 #define ll long long
 8 #define mk make_pair
 9 #define pb push_back
10 #define se second
11 #define fi first
12 #define rs o<<1|1
13 #define ls o<<1
14 ll mod=998244353;
15 const int N=2e3+5;
16 int T,n;
17 int X[N],Y[N];
18 struct node{
19     int x,y;
20     ll w;
21 }a[N];
22 vectorg[N];
23 ll sum[N*4],L[N*4],R[N*4],mx[N*4];
24 void push(int o){
25     sum[o]=sum[ls]+sum[rs];
26     L[o]=max(L[ls],sum[ls]+L[rs]);
27     R[o]=max(R[rs],sum[rs]+R[ls]);
28     ll t1=max(mx[ls],mx[rs]);
29     ll t2=max(t1,R[ls]+L[rs]);
30     mx[o]=0;
31     mx[o]=max(mx[o],t2);
32 }
33 void up(int o,int l,int r,int k,ll w){
34     if(l==r){
35         sum[o]+=w;
36         L[o]+=w;
37         R[o]+=w;
38         mx[o]+=w;
39         return;
40     }
41     int m=(l+r)/2;
42     if(k<=m)up(ls,l,m,k,w);
43     else up(rs,m+1,r,k,w);
44     push(o);
45 }
46 int main(){
47     scanf("%d",&T);
48     while(T--){
49         scanf("%d",&n);
50         for(int i=1;i<=n;i++){
51             scanf("%d%d%lld",&a[i].x,&a[i].y,&a[i].w);
52             X[i]=a[i].x;
53             Y[i]=a[i].y;
54         }
55         sort(X+1,X+1+n);
56         sort(Y+1,Y+1+n);
57 
58         int sz1=unique(X+1,X+1+n)-X-1;
59         int sz2=unique(Y+1,Y+1+n)-Y-1;
60 
61         for(int i=1;i<=n;i++){
62             a[i].x=lower_bound(X+1,X+1+sz1,a[i].x)-X;
63             a[i].y=lower_bound(Y+1,Y+1+sz2,a[i].y)-Y;
64             g[a[i].y].pb(mk(a[i].x,a[i].w));
65         }
66         ll ans=0;
67         for(int i=1;i<=sz2;i++){
68             for(int j=1;j<=sz1*4;j++){
69                 sum[j]=L[j]=R[j]=mx[j]=0;
70             }
71             for(int j=i;j>=1;j--){
72                 for(int k=0;k){
73                     pa t=g[j][k];
74                     up(1,1,sz1,t.fi,t.se);
75                 }
76                 ans=max(ans,mx[1]);
77             }
78         }
79         printf("%lld\n",ans);
80         for(int i=1;i<=sz2;i++)g[i].clear();
81     }
82 }

 

你可能感兴趣的:(HDU 6638 Snowy Smile(线段树求二维最大连续子段和))