zoukankan      html  css  js  c++  java
  • [vijos]1083小白逛公园<线段树>

    描述

    小新经常陪小白去公园玩,也就是所谓的遛狗啦…在小新家附近有一条“公园路”,路的一边从南到北依次排着n个公园,小白早就看花了眼,自己也不清楚该去哪些公园玩了。

    一开始,小白就根据公园的风景给每个公园打了分-.-。小新为了省事,每次遛狗的时候都会事先规定一个范围,小白只可以选择第a个和第b个公园之间(包括a、b两个公园)选择**连续**的一些公园玩。小白当然希望选出的公园的分数总和尽量高咯。同时,由于一些公园的景观会有所改变,所以,小白的打分也可能会有一些变化。

    那么,就请你来帮小白选择公园吧。

    格式

    输入格式

    第一行,两个整数N和M,分别表示表示公园的数量和操作(遛狗或者改变打分)总数。

    接下来N行,每行一个整数,依次给出小白 开始时对公园的打分。

    接下来M行,每行三个整数。第一个整数K,1或2。K=1表示,小新要带小白出去玩,接下来的两个整数a和b给出了选择公园的范围(1≤a,b≤N, a可以大于b!);K=2表示,小白改变了对某个公园的打分,接下来的两个整数p和s,表示小白对第p个公园的打分变成了s(1≤p≤N)。

    其中,1≤N≤500 000,1≤M≤100 000,所有打分都是绝对值不超过1000的整数。

    输出格式

    小白每出去玩一次,都对应输出一行,只包含一个整数,表示小白可以选出的公园得分和的最大值。

    样例1

    样例输入1

    5 3
    1 2 -3 4 5
    1 2 3
    2 2 -1
    1 2 3
    
    

    样例输出1

    2
    -1
    

    限制

    各个测试点2s

    这是一道线段树的题,和一般不同的是这道题求一个区间内连续几个的最大值,这个就要多定义一个从左边开始和从右边开始的连续最大值lmax和rmax

    在简单的提醒后,很快的把题的大部分打完了,最后卡在询问环节,还是多亏了大佬Ztraveler的帮助点醒了我

    我就简单的提一下我卡住的地方

    当我们要求出的L和R区间的LR在mid的同一侧就是一个简单的询问操作,但是当L和R分居mid的两侧时,就要稍作处理

    我和那位大佬的方法是新开三个结构体,ly,ry,yy,分别是L到mid,mid+1到R和L到R,这样下来就可以就出L到R中的答案了

    然后再提醒一点小细节,就是查询时a可能大于b也可能小于b

    说的可能不是很清晰,还是看代码分析吧

      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 #include<algorithm>
      5 #include<iostream>
      6 #include<cstdlib>
      7 #define maxn 500005
      8 #define lson pos<<1
      9 #define rson pos<<1|1
     10 using namespace std;
     11 
     12 struct node{
     13     int sum,l,r,lmax,rmax,maxx;
     14 }e[maxn*4];
     15 
     16 int a[maxn],n,m;
     17 
     18 void pushup(int pos)//更新操作 
     19 {
     20         e[pos].sum=e[lson].sum+e[rson].sum;
     21         e[pos].lmax=max(e[lson].lmax,e[lson].sum+e[rson].lmax);
     22         e[pos].rmax=max(e[rson].rmax,e[rson].sum+e[lson].rmax);
     23         e[pos].maxx=max(max(max(e[lson].lmax,e[rson].rmax),e[lson].rmax+e[rson].lmax),max(e[lson].maxx,e[rson].maxx));
     24 }
     25 
     26 void build(int l,int r,int pos)
     27 {
     28     e[pos].l=l;e[pos].r=r;
     29     if(l==r)
     30     {
     31         e[pos].lmax=a[l];
     32         e[pos].rmax=a[l];
     33         e[pos].maxx=a[l];
     34         e[pos].sum =a[l];
     35     }else{    
     36         int mid=(l+r)>>1;
     37         build(l,mid,lson);
     38         build(mid+1,r,rson);
     39         pushup(pos);
     40     }
     41 }    
     42 
     43 node  query(int l,int r,int pos)
     44 {
     45     if(e[pos].l==l&&e[pos].r==r)
     46     {
     47         return e[pos];
     48     }else{
     49         int mid=(e[pos].l+e[pos].r)>>1;
     50         if(mid>=r){
     51             return query(l,r,pos<<1);
     52         }else{
     53             if(mid<l)return query(l,r,pos<<1|1);
     54             else {//当要找的LR分居mid两侧 
     55                 node ly=query(l,mid,lson);
     56                 node ry=query(mid+1,r,rson);
     57                 node yy;
     58                 yy.sum=ly.sum+ry.sum;
     59                 yy.lmax=max(ly.lmax,ly.sum+ry.lmax);
     60                 yy.rmax=max(ry.rmax,ry.sum+ly.rmax);
     61                 yy.maxx=max(max(max(ly.lmax,ry.rmax),ly.rmax+ry.lmax),max(ly.maxx,ry.maxx));
     62                 return yy;
     63             }
     64         }
     65     }
     66 }
     67 
     68 void change(int l,int r,int k,int x,int pos)
     69 {
     70     if(l==k&&r==k)
     71     {
     72         e[pos].lmax=e[pos].rmax=e[pos].maxx=e[pos].sum=x;
     73     }else{
     74         int mid=(l+r)>>1;
     75         if(k<=mid)
     76         {
     77             change(l,mid,k,x,pos<<1);
     78             pushup(pos);
     79         
     80         }else{
     81             change(mid+1,r,k,x,pos<<1|1);
     82             pushup(pos);
     83         }    
     84     }
     85 }
     86 
     87 int main()
     88 {
     89     scanf("%d%d",&n,&m);
     90     for(int i=1;i<=n;i++)
     91     {
     92         scanf("%d",&a[i]);    
     93     }
     94     build(1,n,1);
     95     for(int i=1;i<=m;i++)
     96     {
     97         int q;
     98         scanf("%d",&q);
     99         if(q==1)
    100         {
    101             int a,b;
    102             scanf("%d%d",&a,&b);
    103             if(a>b)printf("%d
    ",query(b,a,1).maxx);
    104             else printf("%d
    ",query(a,b,1).maxx);//不要被这个小细节坑了
    105         }else{
    106             int a,b;
    107             scanf("%d%d",&a,&b);
    108             change(1,n,a,b,1);
    109         }
    110     } 
    111 }

    做完这题整个人都不好了,感觉这点细节都看不到,我的oi之路艰难啊!!!

    ps:代码写的比较稀疏,看起来很多,其实不难的

     

  • 相关阅读:
    Platform创建WinCE内核时的编译错误
    evc4下载
    WinCE NK.bin与NK.nb0
    怎样安装SQL Server CE
    WinCE 5.0 & its eboot
    WinCE 5.0边做边学(4)
    nema协议解析
    wince romfs的一点讨论
    学习VC++时经常会遇到链接错误LNK2001
    wince 来电防火墙静音实现的几种办法
  • 原文地址:https://www.cnblogs.com/Danzel-Aria233/p/7196442.html
Copyright © 2011-2022 走看看