数据结构 解题报告
数据结构
给一个长为\(n\)的\(A\),定义\(n\times n\)的\(B_{l,r}=\sum\limits_{i=l}^rA_i\),两个操作,修改\(A_p\)为\(x\),询问\(B_{l,r}\)的历史最小值。
我居然把D1T1鸽到D4晚上...
历史最值+kd-tree
先离线的把点放到kd-tree中(要离散化)
然后就是矩形加和单点查询,打一下历史最值的标记就好了
我主要还是熟悉一下kd-tree,第三次打这玩意儿
注意kd-tree查询点应该怎么写
Code:
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define ll long long
const int N=1e5+5;
using std::min;
using std::max;
template <class T>
void read(T &x)
{
x=0;char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) x=x*10+c-'0',c=getchar();
}
int ch[N][2],L[N][2],R[N][2],pos[N][2],num[N],tot,root;
ll mi[N],dat[N],tag[N],histag[N],f[N];
#define ls ch[now][0]
#define rs ch[now][1]
void updata(int now)
{
L[now][0]=R[now][0]=pos[now][0];
L[now][1]=R[now][1]=pos[now][1];
if(ls)
{
L[now][0]=min(L[now][0],L[ls][0]);
L[now][1]=min(L[now][1],L[ls][1]);
R[now][0]=max(R[now][0],R[ls][0]);
R[now][1]=max(R[now][1],R[ls][1]);
}
if(rs)
{
L[now][0]=min(L[now][0],L[rs][0]);
L[now][1]=min(L[now][1],L[rs][1]);
R[now][0]=max(R[now][0],R[rs][0]);
R[now][1]=max(R[now][1],R[rs][1]);
}
}
void pushdown(int now)
{
if(tag[now])
{
if(ls)
{
mi[ls]=min(mi[ls],dat[ls]+histag[now]);
dat[ls]+=tag[now];
histag[ls]=min(histag[ls],tag[ls]+histag[now]);
tag[ls]+=tag[now];
}
if(rs)
{
mi[rs]=min(mi[rs],dat[rs]+histag[now]);
dat[rs]+=tag[now];
histag[rs]=min(histag[rs],tag[rs]+histag[now]);
tag[rs]+=tag[now];
}
tag[now]=histag[now]=0;
}
}
int nk;
bool cmp(int a,int b)
{
return pos[a][nk]==pos[b][nk]?pos[a][nk^1]<pos[b][nk^1]:pos[a][nk]<pos[b][nk];
}
void build(int &now,int l,int r,int k)
{
if(l>r){now=0;return;}
int mid=l+r>>1;nk=k;
std::nth_element(num+l,num+mid,num+r+1,cmp);
now=num[mid];
build(ls,l,mid-1,k^1),build(rs,mid+1,r,k^1);
updata(now);
}
bool ckm(int a,int b,int c,int d){return b<c||a>d;}
bool ck(int a,int b,int c,int d){return a<=c&&d<=b;}
void modi(int now,int a,int b,int c,int d,int delta)
{
if(!now) return;
if(ckm(L[now][0],R[now][0],a,c)||ckm(L[now][1],R[now][1],b,d)) return;
if(ck(a,c,L[now][0],R[now][0])&&ck(b,d,L[now][1],R[now][1]))
{
mi[now]=min(mi[now],dat[now]+delta);
dat[now]+=delta;
histag[now]=min(histag[now],tag[now]+delta);
tag[now]+=delta;
return;
}
pushdown(now);
if(a<=pos[now][0]&&pos[now][0]<=c&&b<=pos[now][1]&&pos[now][1]<=d)
{
dat[now]=dat[now]+delta;
mi[now]=min(mi[now],dat[now]);
}
modi(ls,a,b,c,d,delta),modi(rs,a,b,c,d,delta);
}
ll query(int now,int a,int b,int k)
{
if(pos[now][0]==a&&pos[now][1]==b) return mi[now];
pushdown(now);
int mid=pos[now][k];
if(k)
{
if(b<pos[now][k]||(b==pos[now][k]&&a<pos[now][k^1])) return query(ls,a,b,k^1);
else return query(rs,a,b,k^1);
}
else
{
if(a<pos[now][k]||(a==pos[now][k]&&b<pos[now][k^1])) return query(ls,a,b,k^1);
else return query(rs,a,b,k^1);
}
}
struct koito_yuu
{
int op,p,x;
}yuu[N];
struct yuyuyu
{
int l,r;
bool friend operator <(yuyuyu a,yuyuyu b)
{
return a.l==b.l?a.r<b.r:a.l<b.l;
}
bool friend operator ==(yuyuyu a,yuyuyu b)
{
return a.l==b.l&&a.r==b.r;
}
}yuy[N];
int n,m,a[N];
int main()
{
//freopen("ds.in","r",stdin);
//freopen("ds.out","w",stdout);
read(n),read(m);
for(int i=1;i<=n;i++) read(a[i]),f[i]=f[i-1]+a[i];
for(int i=1;i<=m;i++)
{
read(yuu[i].op);
if(yuu[i].op==1)
{
read(yuu[i].p);
read(yuu[i].x);
}
if(yuu[i].op==2)
{
++tot;
read(yuy[tot].l);
read(yuy[tot].r);
yuu[i].p=yuy[tot].l,yuu[i].x=yuy[tot].r;
}
}
std::sort(yuy+1,yuy+1+tot);
tot=std::unique(yuy+1,yuy+1+tot)-yuy-1;
for(int i=1;i<=tot;i++)
{
num[i]=i;
pos[i][0]=yuy[i].l;
pos[i][1]=yuy[i].r;
dat[i]=mi[i]=f[yuy[i].r]-f[yuy[i].l-1];
}
build(root,1,tot,0);
for(int i=1;i<=m;i++)
{
if(yuu[i].op==1) modi(root,1,yuu[i].p,yuu[i].p,n,yuu[i].x-a[yuu[i].p]),a[yuu[i].p]=yuu[i].x;
else printf("%lld\n",query(root,yuu[i].p,yuu[i].x,0));
}
return 0;
}
2019.3.24