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;
}
View Code

 

posted @ 2019-03-27 20:39  Jessiejzy  阅读(471)  评论(0编辑  收藏  举报