51nod 1768 Rikka with Sequences KDtree维护历史最大值
来源:互联网 发布:签名设计图软件 编辑:程序博客网 时间:2024/06/06 07:37
题意
众所周知,萌萌哒六花不擅长数学,所以勇太给了她一些数学问题做练习,其中有一道是这样的:
勇太有一个长度为 n 的数组A 和一个大小为n×n 的二维数组B,最开始
接下来勇太进行了两种操作:
1. 给出两个整数
2. 给出两个整数
在每次操作之后,勇太都会进行一次更新:
为了锻炼六花的计算能力,勇太希望六花能够尽可能快地回答他的问题。
当然,这个问题对于萌萌哒六花来说实在是太难了,你可以帮帮她吗?
输入数据保证
分析
要做这题首先你要会维护历史最值。如果不会的话可以先看这里。
我们可以把操作里面,把一个询问(l,r)看做二维平面上的一个点。
那么一次修改操作,就相当于把横坐标不大于l且纵坐标不小于l的点加上一个数。
这个的话可以用KDtree打标记来维护。
复杂度的话。。。不是很会证,据题解说是
代码
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>using namespace std;typedef long long LL;const int N=100005;int n,m,D,tot;LL s[N],a[N];struct tree{int d[2],mn[2],mx[2],l,r;LL add,add1,val,mn1;}t[N];struct data{int op,l,r;}q[N];int read(){ int x=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f;}bool cmp(tree a,tree b){ return a.d[D]<b.d[D]||a.d[D]==b.d[D]&&a.d[D^1]<b.d[D^1];}void maintain(int x,int y){ t[x].mn[0]=min(t[x].mn[0],t[y].mn[0]); t[x].mn[1]=min(t[x].mn[1],t[y].mn[1]); t[x].mx[0]=max(t[x].mx[0],t[y].mx[0]); t[x].mx[1]=max(t[x].mx[1],t[y].mx[1]);}void push_add(int d,LL w){ t[d].add+=w;t[d].add1=min(t[d].add1,t[d].add); t[d].val+=w;t[d].mn1=min(t[d].val,t[d].mn1);}void pushdown(int d){ if (t[d].l) { int x=t[d].l; t[x].mn1=min(t[x].mn1,t[x].val+t[d].add1); t[x].add1=min(t[x].add1,t[x].add+t[d].add1); push_add(x,t[d].add); } if (t[d].r) { int x=t[d].r; t[x].mn1=min(t[x].mn1,t[x].val+t[d].add1); t[x].add1=min(t[x].add1,t[x].add+t[d].add1); push_add(x,t[d].add); } t[d].add=t[d].add1=0;}int build(int l,int r,int DD){ D=DD;int mid=(l+r)/2; nth_element(t+l,t+mid,t+r+1,cmp); t[mid].mn[0]=t[mid].mx[0]=t[mid].d[0]; t[mid].mn[1]=t[mid].mx[1]=t[mid].d[1]; if (l<mid) t[mid].l=build(l,mid-1,DD^1),maintain(mid,t[mid].l); if (r>mid) t[mid].r=build(mid+1,r,DD^1),maintain(mid,t[mid].r); return mid;}void ins(int d,int x1,int x2,int y1,int y2,LL w){ if (t[d].mn[0]>x2||t[d].mx[0]<x1||t[d].mn[1]>y2||t[d].mx[1]<y1) return; pushdown(d); if (t[d].mn[0]>=x1&&t[d].mx[0]<=x2&&t[d].mn[1]>=y1&&t[d].mx[1]<=y2) { push_add(d,w); return; } if (t[d].d[0]>=x1&&t[d].d[0]<=x2&&t[d].d[1]>=y1&&t[d].d[1]<=y2) t[d].val+=w,t[d].mn1=min(t[d].val,t[d].mn1); if (t[d].l) ins(t[d].l,x1,x2,y1,y2,w); if (t[d].r) ins(t[d].r,x1,x2,y1,y2,w);}LL query(int d,int x,int y,int DD){ pushdown(d); if (t[d].d[0]==x&&t[d].d[1]==y) return t[d].mn1; if (!DD) if (x<t[d].d[0]||x==t[d].d[0]&&y<t[d].d[1]) return query(t[d].l,x,y,DD^1); else return query(t[d].r,x,y,DD^1); else if (y<t[d].d[1]||y==t[d].d[1]&&x<t[d].d[0]) return query(t[d].l,x,y,DD^1); else return query(t[d].r,x,y,DD^1);}int main(){ n=read();m=read(); for (int i=1;i<=n;i++) a[i]=read(),s[i]=a[i]+s[i-1]; for (int i=1;i<=m;i++) { q[i].op=read(),q[i].l=read(),q[i].r=read(); if (q[i].op==1) continue; tot++; t[tot].d[0]=q[i].l;t[tot].d[1]=q[i].r; t[tot].val=t[tot].mn1=s[q[i].r]-s[q[i].l-1]; } int root=build(1,tot,0); for (int i=1;i<=m;i++) { if (q[i].op==1) { ins(root,1,q[i].l,q[i].l,n,q[i].r-a[q[i].l]); a[q[i].l]=q[i].r; } else printf("%lld\n",query(root,q[i].l,q[i].r,0)); } return 0;}
阅读全文
0 0
- 51nod 1768 Rikka with Sequences KDtree维护历史最大值
- [51nod1768]Rikka with Sequences
- 51Nod - 1133 dp + 二分 + 维护最大值
- 51nod 1376【线段树维护区间最大值】
- 51nod 1402最大值
- 51NOD 1402 最大值
- 51nod 1402 最大值
- 51Nod 1402 最大值
- 【51NOD 1666】最大值
- 51nod 1402 最大值
- 51nod 1163 最大值
- 51Nod-1349-最大值
- 51nod 1349 最大值
- 51Nod 1349 最大值
- 51Nod 1402 最大值问题
- 51nod 1402 最大值 【-.-思维??--】
- 51nod 1402 最大值问题
- BZOJ 3064 Tyvj 1518 CPU监控 线段树维护历史最大值
- APP界面设计之页面布局的22条基本原则
- 回溯法解决8皇后问题
- python--leetcode104. Maximum Depth of Binary Tree
- 微信开发访问两次服务器
- 使用RUBY遍历目录下的所有文件
- 51nod 1768 Rikka with Sequences KDtree维护历史最大值
- python 短路法提高二叉堆插入效率
- springboot2入门(4-starter-hateoas)
- OpenCV外接USB摄像头
- java知识体系
- Ubuntu扩展硬盘及分区
- CSS3过渡
- Linux中的自动安装脚本
- 使用CSDN-markdown写数学公式