博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
NKOJ-1316 小白逛公园
阅读量:5817 次
发布时间:2019-06-18

本文共 2322 字,大约阅读时间需要 7 分钟。

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\n",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));
}

转载于:https://www.cnblogs.com/c201904xyorz/p/9990782.html

你可能感兴趣的文章
Binary Search Tree Iterator leetcode
查看>>
Oracle性能优化--DBMS_PROFILER
查看>>
uva-317-找规律
查看>>
Event事件的兼容性(转)
查看>>
我的2014-相对奢侈的生活
查看>>
zoj 2412 dfs 求连通分量的个数
查看>>
Java设计模式
查看>>
一文读懂 AOP | 你想要的最全面 AOP 方法探讨
查看>>
Spring Cloud 微服务分布式链路跟踪 Sleuth 与 Zipkin
查看>>
ORM数据库框架 SQLite 常用数据库框架比较 MD
查看>>
华为OJ 名字美丽度
查看>>
微信公众号与APP微信第三方登录账号打通
查看>>
onchange()事件的应用
查看>>
Windows 下最佳的 C++ 开发的 IDE 是什么?
查看>>
软件工程师成长为架构师必备的十项技能
查看>>
python 异常
查看>>
百度账号注销
查看>>
mysql-This version of MySQL doesn’t yet support ‘LIMIT & IN/ALL/ANY/SOME 错误解决
查看>>
BIEE Demo(RPD创建 + 分析 +仪表盘 )
查看>>
Cocos2dx 3.0开发环境的搭建--Eclipse建立在Android工程
查看>>