标签:using void printf bool ring 转化 标记 int() str
分析:
这道题可以看做单点修改区间查询历史最小值的数据结构题
区间修改单点查询历史版本可以使用二维数据结构维护
由于卡空间,这里只能选择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);
}
}
标签:using void printf bool ring 转化 标记 int() str
原文地址:https://www.cnblogs.com/Darknesses/p/12961052.html