zoukankan      html  css  js  c++  java
  • NKOJ-1316 小白逛公园

    http://oi.nks.edu.cn/en/Problem/Details/1316
    小新经常陪小白去公园玩,也就是所谓的遛狗啦…在小新家附近有一条“公园路”,
    路的一边从南到北依次排着n个公园,小白早就看花了眼,自己也不清楚该去哪些公园玩了。
    一开始,小白就根据公园的风景给每个公园打了分-.-。小新为了省事,
    每次遛狗的时候都会事先规定一个范围,小白只可以选择第a个和第b个公园之间
    (包括a、b两个公园)选择连续的一些公园玩。
    小白当然希望选出的公园的分数总和尽量高咯。
    同时,由于一些公园的景观会有所改变,
    所以,小白的打分也可能会有一些变化。那么,就请你来帮小白选择公园吧。


    这道题,其实是并不是非常难,只不过楼主卡了很久才过的:
    首先我们先建树:然后再进行更新或者询问,更新是简单的点更新,
    具体询问看下面 
    #include<cstdio>
    #include<iostream>
    using namespace std;
    const int Max=2e6+5;
    int l[Max],r[Max];//左端点和右端点 
    int lmax[Max],rmax[Max],maxx[Max];
    //lmax指从最左边往右开始算的线段最大,rmax指从最有右边往左开始算的线段最大,
    //而maxx指的是这一段中和最大的一段 
    int sum[Max];//只这一段所有景点值的和 
    int s[500005];
    int s1;
    int n,m;
    int xx,yy;
    int getl(int i){//算左边最大 
    return max(lmax[i],sum[i]+lmax[i+1]);
    }
    int getr(int i){//算右边最大 
    return max(rmax[i+1],sum[i+1]+rmax[i]);
    }
    int get(int i){//算综合最大 
    return max(max(maxx[i],maxx[i+1]),rmax[i]+lmax[i+1]);
    }
    void magic(int x,int y){
    sum[y]=lmax[y]=rmax[y]=maxx[y]=x;
    }
    void buildtree(){
    s1=1;
    while(s1<n)s1*=2;
    for(int i=s1*2-1;i>=s1;i--){
    l[i]=r[i]=i-s1+1;
    magic(s[i-s1+1],i);
    }
    for(int i=s1-1;i>=1;i--){
            l[i]=l[i<<1],r[i]=r[(i<<1)+1];
        sum[i]=sum[(i<<1)+1]+sum[i<<1];
        lmax[i]=getl((i<<1));rmax[i]=getr((i<<1));
    maxx[i]=get((i<<1));
    }
    }
    void update(int x,int y){
    magic(x,y);
    while(y){
    y/=2; 
        sum[y]=sum[(y<<1)+1]+sum[y<<1];
        lmax[y]=getl((y<<1));rmax[y]=getr((y<<1));maxx[y]=get((y<<1));
    }
    }
    int ask(int l,int r,int i);
    int getleft(int l1,int r1,int i){
    if(r1==r[i])return lmax[i];
    int mid=(l[i]+r[i])/2;
        if(mid>=r1)return getleft(l1,r1,i*2);
    else return max(sum[2*i]+getleft(mid+1,r1,i*2+1),lmax[i*2]);
    }
    int getright(int l1,int r1,int i){
    if(l1==l[i])return rmax[i];
    int mid=(l[i]+r[i])/2;
        if(l1>mid)return getright(l1,r1,i*2+1);
    else return max(sum[2*i+1]+getright(l1,mid,i*2),rmax[i*2+1]);
    }
    int k,x,y;
    int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%d",&s[i]);
    buildtree();
    for(int i=1;i<=m;i++){
    scanf("%d%d%d",&k,&x,&y);
    if(k==2)update(y,x+s1-1);
    else {
    if(x>y)swap(x,y);
       printf("%d ",ask(x,y,1));
        }
    }
        return 0;
    }
    int ask(int l1,int r1,int i){
    if(l1<=l[i]&&r1>=r[i])return maxx[i];
    int mid=(l[i]+r[i])/2,xx,yy;
        if(r1<=mid)return ask(l1,r1,i*2);
        else if(l1>mid)return ask(l1,r1,i*2+1);
    else{
    xx=ask(l1,mid,2*i);
    yy=ask(mid+1,r1,2*i+1);
    return max(max(xx,yy),getleft(mid+1,r1,2*i+1)+getright(l1,mid,2*i));

    }
  • 相关阅读:
    [极客大挑战 2019]BuyFlag
    [极客大挑战 2019]BabySQL
    [网鼎杯 2018]Fakebook
    C语言学习笔记_内存数据和字符串
    剑指OFFER_数据流中的中位数
    剑指OFFER_滑动窗口的最大值
    剑指OFFER_矩阵中的路径
    C语言学习笔记_指针相关知识
    剑指OFFER_机器人的运动范围
    剑指OFFER_剪绳子
  • 原文地址:https://www.cnblogs.com/c201904xyorz/p/9990782.html
Copyright © 2011-2022 走看看