联考20200525 T1 数据结构
分析:
这道题可以看做单点修改区间查询历史最小值的数据结构题
区间修改单点查询历史版本可以使用二维数据结构维护
由于卡空间,这里只能选择KD树
在KD树上区间修改,历史最值只需要统计单点到根节点的路径上记录的历史最值就行了
关键是这道题如何转化?
我们把询问离线,每一个查询\((l,r)\)看做坐标轴上的单点
单点\(x\)的修改可以看做对横坐标为\([1,x]\)纵坐标\([x,n]\)的矩形区间修改
于是转化成了区间修改单点查询
KD树上每个节点存储当前状态和懒标记状态(状态包含当前值和历史最值)
#include<cstdio> #include<cstring> #include<cmath> #include<iostream> #include<queue> #include<algorithm> #define maxn 200005 #define INF 0x3f3f3f3f using namespace std; inline int getint() { int num=0,flag=1;char c; while((c=getchar())<‘0‘||c>‘9‘)if(c==‘-‘)flag=-1; while(c>=‘0‘&&c<=‘9‘)num=num*10+c-48,c=getchar(); return num*flag; } int n,m,N,rt; int a[maxn],op[maxn],x[maxn],y[maxn],id[maxn]; long long sum[maxn]; struct data{ long long num,mn; data(){}data(long long x){num=mn=x;} inline void update(data p){mn=min(mn,num+p.mn),num+=p.num;} }; struct node{ int d[2],mn[2],mx[2],ch[2],fa; data val,lz; }t[maxn]; inline bool cmp0(int x,int y){return t[x].d[0]<t[y].d[0];} inline bool cmp1(int x,int y){return t[x].d[1]<t[y].d[1];} inline void update(node &p) { p.mn[0]=p.mx[0]=p.d[0],p.mn[1]=p.mx[1]=p.d[1]; for(int i=0;i<2;i++)if(p.ch[i])for(int j=0;j<2;j++) p.mn[j]=min(p.mn[j],t[p.ch[i]].mn[j]),p.mx[j]=max(p.mx[j],t[p.ch[i]].mx[j]); } inline void pushdown(int i) { if(t[i].lz.mn||t[i].lz.num) { if(t[i].ch[0])t[t[i].ch[0]].val.update(t[i].lz),t[t[i].ch[0]].lz.update(t[i].lz); if(t[i].ch[1])t[t[i].ch[1]].val.update(t[i].lz),t[t[i].ch[1]].lz.update(t[i].lz); t[i].lz=data(0); } } inline void build(int &now,int l,int r,int D) { int mid=(l+r)>>1; nth_element(id+l,id+mid,id+r+1,D?cmp1:cmp0);now=id[mid]; if(l<mid)build(t[now].ch[0],l,mid-1,D^1); if(mid<r)build(t[now].ch[1],mid+1,r,D^1); t[t[now].ch[0]].fa=t[t[now].ch[1]].fa=now; update(t[now]); } inline void update(int i,int num,int p) { if(!i||p<t[i].mn[0]||p>t[i].mx[1])return; if(p>=t[i].mx[0]&&p<=t[i].mn[1]){t[i].val.update(data(num)),t[i].lz.update(data(num));return;} pushdown(i); if(p>=t[i].d[0]&&p<=t[i].d[1])t[i].val.update(data(num)); update(t[i].ch[0],num,p),update(t[i].ch[1],num,p); } inline void pdpath(int x){if(t[x].fa)pdpath(t[x].fa);pushdown(x);} int main() { n=getint(),m=getint(); for(int i=1;i<=n;i++)sum[i]=sum[i-1]+(a[i]=getint()); for(int i=1;i<=m;i++) { op[i]=getint(),x[i]=getint(),y[i]=getint(); if(op[i]==2)t[++N].d[0]=x[i],t[N].d[1]=y[i],t[N].val=data(sum[y[i]]-sum[x[i]-1]),id[N]=N; } build(rt,1,N,0); for(int i=1,k=0;i<=m;i++) { if(op[i]&1)update(rt,y[i]-a[x[i]],x[i]),a[x[i]]=y[i]; else pdpath(++k),printf("%lld\n",t[k].val.mn); } }