小白逛公园
2015-06-24 12:51
295 查看
小白逛公园
Time Limit:20000MS Memory Limit:65536K
Case Time Limit:2000MS
Description
小新经常陪小白去公园玩,也就是所谓的遛狗啦…在小新家附近有一条“公园路”,路的一边从南到北依次排着n个公园,小白早就看花了眼,自己也不清楚该去哪些公园玩了。
一开始,小白就根据公园的风景给每个公园打了分-.-。小新为了省事,每次遛狗的时候都会事先规定一个范围,小白只可以选择第a个和第b个公园之间(包括a、b两个公园)选择连续的一些公园玩。小白当然希望选出的公园的分数总和尽量高咯。同时,由于一些公园的景观会有所改变,所以,小白的打分也可能会有一些变化。
那么,就请你来帮小白选择公园吧。
Input
第一行,两个整数N和M,分别表示表示公园的数量和操作(遛狗或者改变打分)总数。
接下来N行,每行一个整数,依次给出小白 开始时对公园的打分。
接下来M行,每行三个整数。第一个整数K,1或2。K=1表示,小新要带小白出去玩,接下来的两个整数a和b给出了选择公园的范围(1≤a,b≤N);K=2表示,小白改变了对某个公园的打分,接下来的两个整数p和s,表示小白对第p个公园的打分变成了s(1≤p≤N)。
其中,1≤N≤500 000,1≤M≤100 000,所有打分都是绝对值不超过1000的整数。
Output
小白每出去玩一次,都对应输出一行,只包含一个整数,表示小白可以选出的公园得分和的最大值。
Sample Input
Sample Output
Source
vijos
Time Limit:20000MS Memory Limit:65536K
Case Time Limit:2000MS
Description
小新经常陪小白去公园玩,也就是所谓的遛狗啦…在小新家附近有一条“公园路”,路的一边从南到北依次排着n个公园,小白早就看花了眼,自己也不清楚该去哪些公园玩了。
一开始,小白就根据公园的风景给每个公园打了分-.-。小新为了省事,每次遛狗的时候都会事先规定一个范围,小白只可以选择第a个和第b个公园之间(包括a、b两个公园)选择连续的一些公园玩。小白当然希望选出的公园的分数总和尽量高咯。同时,由于一些公园的景观会有所改变,所以,小白的打分也可能会有一些变化。
那么,就请你来帮小白选择公园吧。
Input
第一行,两个整数N和M,分别表示表示公园的数量和操作(遛狗或者改变打分)总数。
接下来N行,每行一个整数,依次给出小白 开始时对公园的打分。
接下来M行,每行三个整数。第一个整数K,1或2。K=1表示,小新要带小白出去玩,接下来的两个整数a和b给出了选择公园的范围(1≤a,b≤N);K=2表示,小白改变了对某个公园的打分,接下来的两个整数p和s,表示小白对第p个公园的打分变成了s(1≤p≤N)。
其中,1≤N≤500 000,1≤M≤100 000,所有打分都是绝对值不超过1000的整数。
Output
小白每出去玩一次,都对应输出一行,只包含一个整数,表示小白可以选出的公园得分和的最大值。
Sample Input
5 3 1 2 -3 4 5 1 2 3 2 2 -1 1 2 3
Sample Output
2 -1
Source
vijos
#include <stdio.h> #define maxn 500000 #define inf -2100000000 inline void _read(int& d) { char t=getchar();bool f=false; while(t<'0'||t>'9') {if(t=='-') f=true; t=getchar();} for(d=0;t<='9'&&t>='0';t=getchar()) d=d*10+t-'0'; if(f) d=-d; } inline void _out(int d) { int o[30],top=1; if(d==0){putchar('0');return ;} if(d<0) {putchar('-');d=-d;} while(d) { o[top++]=d%10; d/=10; } for(--top;top;--top) putchar('0'+o[top]); } struct node{int a, b, l, r, lmax, rmax, max, sum;}tree[maxn*2+9]; int mark[maxn+9], tot=0; int rofmax2(int a, int b) { if(a>b) return a; return b; } int rofmax3(int a, int b, int c) { return rofmax2(rofmax2(a, b), c); } int Min(int a, int b) { if(a<b) return a; return b; } void updata(int now) { //以下全部维护当前区间的数据 int ls=tree[now].l, rs=tree[now].r; tree[now].sum=tree[ls].sum+tree[rs].sum; //维护区间和 tree[now].lmax=rofmax2(tree[ls].lmax, tree[ls].sum+tree[rs].lmax); //维护左起最长连续和 tree[now].rmax=rofmax2(tree[rs].rmax, tree[rs].sum+tree[ls].rmax); //维护右起最长连续和 tree[now].max=rofmax3(tree[ls].max, tree[rs].max, tree[ls].rmax+tree[rs].lmax); //维护最长区间和 } void maketree(int x, int y) { int now=++tot; tree[now].a=x; tree[now].b=y; tree[now].lmax=tree[now].rmax=tree[now].max=tree[now].sum=inf; if(x==y) { tree[now].l=0; tree[now].r=0; tree[now].max=tree[now].lmax=tree[now].rmax=tree[now].sum=mark[x]; return; } tree[now].l=tot+1; maketree(x, (x+y)/2); tree[now].r=tot+1; maketree((x+y)/2+1, y); updata(now); } int _search_right(int i, int l, int r) { int t=-2100000000; if(l<=tree[i].a) return tree[i].rmax; if(tree[i].r)t=rofmax2(t, _search_right(tree[i].r, l, r)); if(tree[i].l&&l<=tree[tree[i].l].b)t=rofmax2(t,tree[tree[i].r].sum+_search_right(tree[i].l, l, r)); return t; } int _search_left(int i, int l, int r) { int t=-2100000000; if(r>=tree[i].b)return tree[i].lmax; //如果当前节点包含于[l, r], 返回当前节点的左起最大连续和 if(tree[i].l)t=rofmax2(t, _search_left(tree[i].l, l, r)); if(tree[i].r&&r>=tree[tree[i].r].a)t=rofmax2(t, tree[tree[i].l].sum+_search_left(tree[i].r, l, r)); return t; } int getans(int p, int l, int r) { if(l<=tree[p].a&&tree[p].b<=r) return tree[p].max; //如果当前节点包含于[l, r], 返回当前节点的最长连续和 int mid=(tree[p].a+tree[p].b)/2, lmax=inf, rmax=inf; if(l<=mid) lmax=getans(tree[p].l, l, r); //左儿子与[l, r]区间相交部分的最长连续和 if(r>mid) rmax=getans(tree[p].r, l, r); //有儿子与[l, r]区间相交部分的最长连续和 int lt=tree[p].l, rt=tree[p].r; int lenm=-2100000000; if(l<=tree[lt].b&&tree[rt].a<=r) //如果左右儿子都与[l, r]相交, { lenm= _search_left(rt, l, r) //固定左边界向右搜索最大连续和 + _search_right(lt, l, r); //固定右边界向左搜索最大连续和 } return rofmax2(lmax, rofmax2(rmax, lenm)); } void change(int now, int k, int s) //第k个公园的分数变为s,当前讨论到 now 点 { if(tree[now].a<=k&&k<=tree[now].b) //如果第k个公园在当前节点表示的区间之内 { if(tree[now].a==tree[now].b) //如果当前节点是叶节点 { tree[now].lmax=tree[now].rmax=tree[now].max=tree[now].sum=s; } else //如果当前节点不是叶节点 { change(tree[now].l, k, s); change(tree[now].r, k, s); updata(now); } } } int main() { int n, m, alt, a, b, p, s; _read(n);_read(m); //n个公园,m个操作 for(int i=1; i<=n; i++) //读入每个公园的分数 { _read(mark[i]); } maketree(1, n); //建树 for(int i=1; i<=m; i++) { _read(alt); if(1==alt) { _read(a); _read(b); //选择公园的范围[a, b] if(a>b) //有可能a>b, 交换a,b { int t=a; a=b; b=t; } _out(getans(1, a, b)); //输出[a, b]最长连续和 putchar('\n'); } else { _read(p); _read(s); change(1, p, s); //第p个公园的分变成s } } return 0; }
相关文章推荐
- python局域网alive ip侦听
- csharp: using wininet.dll
- 勾兑应收余额大于明细处理
- Android之MediaStore使用的点点滴滴
- CSS控制checkbox样式
- TCP/IP详解学习笔记(14)-TCP连接的未来和性能(未写完)
- JavaScript 给表格排序
- DFX可服务性可靠性安全性测试知识
- TCP/IP详解学习笔记(13)-TCP坚持定时器,TCP保活定时器
- python hook监听事件
- javascript一些面试常用的问题总结
- python hook监听事件
- TCP/IP详解学习笔记(12)-TCP的超时与重传
- 页面调用
- namenode倒换原因分析
- 菜鸟学自动化测试(二)----selenium IDE 功能扩展
- poj2778 DNA Sequence(AC自动机+矩阵快速幂 )
- 冒泡排序
- select into 和 insert into select 两种表复制语句
- spring 拦截器 MethodInterceptor 配置 config aop