数据结构 解题报告

数据结构

给一个长为\(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

猜你喜欢

转载自www.cnblogs.com/butterflydew/p/10590334.html