zoukankan      html  css  js  c++  java
  • [hdu-6638]Snowy Smile 线段树维护 带修改的区间最大字段和 最大子矩阵 2019多校6

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

    题目大意:给n个点 的坐标和权值,画一个矩形(边平行于坐标轴),矩形的值为矩形内部和边界所有点的和,求最大的矩形的值。

    题解:求最大的子矩阵和
    因为点的坐标x,y范围太大,先离散,变为1~2000内的数
    把x放到数组里排序去重,二分查找下标(y相同)
    先说一开始想的几个TLE的方法


    1.直接二维差分 维护二维前缀和 ,暴力枚举每一个矩形  O(N^4)
    2.dp O(N^3)
    求最大字段和的方法  dp[i]为以i为结尾的最大的字段和 dp[i]=max (dp[i-1]+a[i],a[i]);
    二维的最大子矩阵的方法: 我们先维护每一列的前缀和
    枚举矩形上下边界l,r,我可以O(1)求出l-r区间内每一列i的和y,直接差分 y=sum[r][i]-sum[l-1][i];
    神奇的事发生了,每一列被压缩成了一个数,又变为了求最大字段和

    3.正解:O(N^2 log(N))
    我们在上一个方法枚举上下边界l,r 后,变为求这个上下边界的最大字段和;
    在移动了一行下边界后,我们把新加入的一行的新点修改———带修改的最大字段和(我们可以用线段树来维护最大字段和)。
    把n个点按横坐标排序,从前往后加入,就按行加入了。

    线段树维护:
    lm 左端点开始的最大字段和
    rm 右端点开始的最大字段和
    sm 这个区间的最大字段和
    tm 这个区间的所有数字和

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define lcnow now<<1
     4 #define rcnow (now<<1)|1
     5 int const maxn=2010;
     6 long long  n,sx[maxn],sy[maxn],mx,my,ans;
     7 struct tree{
     8     long long  lm,rm,sm,tm;
     9 }tr[maxn<<4];
    10 struct node{
    11     long long  a, b,v;
    12 }no[maxn];
    13 inline long long  get_num(){
    14     char ch;
    15     bool flag=false;
    16     long long  num=0;
    17     ch=getchar();
    18     while(ch<'0'||ch>'9'){if(ch=='-')flag=true;ch=getchar();}
    19     while(ch>='0'&&ch<='9'){num=(num<<3)+(num<<1)+ch-'0';ch=getchar();}
    20     if(flag)return -1*num;
    21     return num;
    22 }
    23 bool cmp2(node x,node y){
    24     return x.a<y.a;
    25 }
    26 void gethash(){
    27     sort(sx+1,sx+1+n);sort(sy+1,sy+1+n);
    28         mx=unique(sx+1,sx+1+n)-sx-1;
    29         my=unique(sy+1,sy+1+n)-sy-1;
    30         long long ax,ay;
    31         for(int i=1;i<=n;i++){
    32             ax=lower_bound(sx+1,sx+1+mx,no[i].a)-sx;
    33             ay=lower_bound(sy+1,sy+1+my,no[i].b)-sy;
    34             no[i].a=ax,no[i].b=ay;
    35         }
    36     sort(no+1,no+1+n,cmp2);
    37 }
    38 void update(int now){//利用儿子更新父亲 
    39     tr[now].tm=tr[lcnow].tm+tr[rcnow].tm;
    40     tr[now].lm=max(tr[lcnow].lm,tr[lcnow].tm+tr[rcnow].lm);
    41     tr[now].rm=max(tr[rcnow].rm,tr[rcnow].tm+tr[lcnow].rm);
    42     tr[now].sm=max(tr[lcnow].sm,tr[rcnow].sm);
    43     tr[now].sm=max(tr[lcnow].rm+tr[rcnow].lm,tr[now].sm);
    44 }
    45 void build(int now,int l,int r){
    46     if(l==r){
    47         tr[now].lm=tr[now].rm=tr[now].sm=tr[now].tm=0;
    48         return;
    49     }
    50     int mid=(l+r)>>1;
    51       build(now<<1,l,mid);
    52       build((now<<1)+1,mid+1,r);
    53       update(now);
    54 } //初始化 
    55 
    56 void change(int now,int l,int r,int x,int v){
    57     //当前点编号now,当前点控制区间 [l,r],要修改的点编号x,加上v 
    58     if(l==r){
    59         tr[now].tm=tr[now].lm=tr[now].rm=tr[now].sm=tr[now].sm+v;
    60         return;
    61     }
    62     int mid=(l+r)>>1;
    63     if(x<=mid)change(now<<1,l,mid,x,v);
    64     else change((now<<1)+1,mid+1,r,x,v);
    65     update(now);
    66 } 
    67 void work(){
    68     memset(tr,0,sizeof tr);
    69     ans=0;
    70     int k;
    71     for(int i=1;i<=n;i++)if(i==1||no[i].a!=no[i-1].a){
    72         build(1,1,my);
    73         for(int j=i;j<=n;j=k){
    74             for( k=j;k<=n&&no[k].a==no[j].a;k++){
    75                 change(1,1,my,no[k].b,no[k].v);
    76             }
    77             if(tr[1].sm>ans)ans=tr[1].sm;
    78         }
    79     }
    80 }
    81 int main(){
    82     long long t;
    83     t=get_num();
    84     while(t--){
    85         n=get_num();
    86         for(int i=1;i<=n;i++){
    87             no[i].a=get_num(),no[i].b=get_num();no[i].v=get_num();
    88             sx[i]=no[i].a,sy[i]=no[i].b;
    89         }
    90         gethash();
    91         work();
    92 
    93         printf("%lld
    ",ans);
    94     }
    95     return 0;
    96 }
  • 相关阅读:
    .NET Core: 在.NET Core中进行单元测试
    .NET: 使用.NET Core CLI开发应用程序
    .NET: 谈谈C#中的扩展方法
    WPF: WPF 中的 Triggers 和 VisualStateManager
    WPF: 只读依赖属性的介绍与实践
    XAML: 自定义控件中事件处理的最佳实践
    .NET: 谈谈共享项目 (Shared Project) 的使用
    UWP: 实现 UWP 应用自启动
    UWP: 通过命令行启动 UWP 应用
    在 .NET中,一种更方便操作配置项的方法
  • 原文地址:https://www.cnblogs.com/conver/p/11318010.html
Copyright © 2011-2022 走看看