dtoj#4298. 数据结构(ds)
题目描述:
对于长度为$n$的初始正整数数列$A$,定义矩阵$B_{n×n}$,初始时$B_{i,j}=\sum\limits_{k=i}^{j}A_k$, 。
有$m$个操作,每个操作为以下两种之一:
- 给出整数$p, x$,将$A_p$修改为$x$。然后对所有的$B_{i,j}$,更新为$min(B_{i,j},\sum\limits_{k=i}^{j} A_k)$。
- 给出整数$l,r$,请回答$B_{l,r}$的值。
算法标签:KD tree
思路:
$KDtree$ 的基本思路是对于二维的问题,交替在一维上进行分治,严格来说效率是和主席树类似的,但是由于特殊的切割方式对于一个区间覆盖到的块更少,同时空间效率也更优秀,是 $O(n)$ 的。网上说这个东西效率是 $O(n\sqrt{n})$ 的,那它就是把...
以下代码:
#include<bits/stdc++.h> #define il inline #define LL long long #define _(d) while(d(isdigit(ch=getchar()))) using namespace std; const int N=1e5+5; LL sum[N]; int a[N],o,pos[N],rt,tot,idx[N],n,m; struct node{ int op,x,y; }f[N]; struct data{ int id,d[2],mn[2],mx[2],fa,ls,rs; LL tag,tm,now,s; bool operator<(const data&t1)const{ return d[o]<t1.d[o]; } }t[N]; il int read(){ int x,f=1;char ch; _(!)ch=='-'?f=-1:f;x=ch^48; _()x=(x<<1)+(x<<3)+(ch^48); return f*x; } il void add(int i,int l,int r){ t[i].id=i;t[i].d[0]=l;t[i].d[1]=r; } il void update(int fa,int x){ t[x].fa=fa; for(int i=0;i<2;i++) t[fa].mx[i]=max(t[fa].mx[i],t[x].mx[i]),t[fa].mn[i]=min(t[fa].mn[i],t[x].mn[i]); } il int build(int l,int r,int op){ int m=(l+r)>>1; o=op;nth_element(t+l,t+m,t+r+1); t[m].mn[0]=t[m].mx[0]=t[m].d[0]; t[m].mn[1]=t[m].mx[1]=t[m].d[1]; if(l<m)t[m].ls=build(l,m-1,op^1),update(m,t[m].ls); if(m<r)t[m].rs=build(m+1,r,op^1),update(m,t[m].rs); return m; } il void W(int x,int y){ t[x].s=min(t[x].s,t[x].now+t[y].tm);t[x].now+=t[y].tag; t[x].tm=min(t[x].tm,t[x].tag+t[y].tm);t[x].tag+=t[y].tag; } il void pushdown(int x){ if(t[x].tag==0&&t[x].tm==0)return; if(t[x].ls)W(t[x].ls,x);if(t[x].rs)W(t[x].rs,x); int kk=t[x].ls; t[x].tag=t[x].tm=0; } il void pushup(int x){ if(t[x].fa>0)pushup(t[x].fa);pushdown(x); } il void Add(int x,int p,int v){ if(!x||t[x].mn[0]>p||t[x].mx[1]<p)return; if(t[x].mx[0]<=p&&t[x].mn[1]>=p){ t[x].tag+=v;t[x].tm=min(t[x].tm,t[x].tag); t[x].now+=v;t[x].s=min(t[x].s,t[x].now); return; } if(t[x].d[0]<=p&&p<=t[x].d[1])t[x].now+=v,t[x].s=min(t[x].s,t[x].now); pushdown(x);Add(t[x].ls,p,v);Add(t[x].rs,p,v); } il LL query(int x){ pushup(x);return t[x].s; } int main() { n=read();m=read(); for(int i=1;i<=n;i++)a[i]=read(),sum[i]=sum[i-1]+a[i]; for(int i=1;i<=m;i++){ int op=read(),x=read(),y=read(); if(op==1){ int v=y-a[x];a[x]=y;f[i]=(node){op,x,v}; } else{ f[i]=(node){op,x,y};add(++tot,x,y);idx[tot]=i; } } rt=build(1,tot,0); for(int i=1;i<=tot;i++)pos[idx[t[i].id]]=i; for(int i=1;i<=m;i++){ if(f[i].op==1)Add(rt,f[i].x,f[i].y); else printf("%lld\n",sum[f[i].y]-sum[f[i].x-1]+query(pos[i])); } return 0; }