UOJ612 【JOISC2021】饮食区

UOJ612 【JOISC2021】饮食区

重工业做法,常数巨大,随手\(rank\)倒数第一。

吉老师线段树、平衡树

显然没法直接维护,参考【ZJOI2016】大森林的做法,把询问离线下来,在区间的左端点插入,右端点后一个位置删除。

这样维护序列只需要一棵平衡树,但是对于一组询问,我们需要准确定位它的位置。容易发现,操作\(2\)其实不需要真正删除,只需要把之后的询问向右平移即可。我们先利用一棵线段树维护不删除情况下每个位置序列的长度,再用一棵线段树维护带删除情况下每个位置序列的长度,然后在第二棵线段树中查询位置,根据查询到的位置与队尾的相对位置关系,即可推出不删除情况下的询问位置。由于第二棵线段树需要每个位置随时对\(0\)\(\max\),需要使用吉老师线段树

\(Code:\)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<vector>
#define N 250005
#define IT vector<ask> :: iterator
#define ll long long
using namespace std;
const ll INF=191919191919191919;
int n,m,q,rt,x,y,z,opt,l,r,c,k,cg,ans[N];
ll b;
#define s(p) tr[p].S
#define tag(p) tr[p].Tag
struct node1
{
    ll S,Tag;
};
struct sgt1
{
    node1 tr[N << 2];
    void push_tag(int p,ll y)
    {
        s(p)+=y,tag(p)+=y;
    }
    void push_down(int p)
    {
        push_tag(p << 1,tag(p));
        push_tag(p << 1 | 1,tag(p));
        tag(p)=0;
    }
    void modify(int p,int l,int r,int x,int y,ll z)
    {
        if (l==x && r==y)
        {
            push_tag(p,z);
            return;
        }
        push_down(p);
        int mid(l+r >> 1);
        if (y<=mid)
            modify(p << 1,l,mid,x,y,z); else
        if (x>mid)
            modify(p << 1 | 1,mid+1,r,x,y,z); else
            {
                modify(p << 1,l,mid,x,mid,z);
                modify(p << 1 | 1,mid+1,r,mid+1,y,z);
            }
    }
    ll calc(int p,int l,int r,int x)
    {
        if (l==r)
            return s(p);
        push_down(p);
        int mid(l+r >> 1);
        if (x<=mid)
            return calc(p << 1,l,mid,x); else
            return calc(p << 1 | 1,mid+1,r,x);
    }
}s1;
#define mn(p) tr[p].Mn
#define se(p) tr[p].Se
#define tag1(p) tr[p].Tag1
#define tag2(p) tr[p].Tag2
struct node2
{
    ll Mn,Se,Tag1,Tag2;
};
struct sgt2
{
    node2 tr[N << 2];
    void build(int p,int l,int r)
    {
        mn(p)=0,se(p)=INF;
        if (l==r)
            return;
        int mid(l+r >> 1);
        build(p << 1,l,mid);
        build(p << 1 | 1,mid+1,r);
    }
    void push_tag(int p,ll t1,ll t2)
    {
        mn(p)+=t1,tag1(p)+=t1;
        if (se(p)!=INF)
            se(p)+=t2,tag2(p)+=t2;
    }
    void push_down(int p)
    {
        ll lt(mn(p << 1)),rt(mn(p << 1 | 1));
        if (lt<=rt)
            push_tag(p << 1,tag1(p),tag2(p)); else
            push_tag(p << 1,tag2(p),tag2(p));
        if (rt<=lt)
            push_tag(p << 1 | 1,tag1(p),tag2(p)); else
            push_tag(p << 1 | 1,tag2(p),tag2(p));
        tag1(p)=tag2(p)=0;
    }
    void update(int p)
    {
        mn(p)=min(mn(p << 1),mn(p << 1 | 1));
        if (mn(p << 1)==mn(p << 1 | 1))
            se(p)=min(se(p << 1),se(p << 1 | 1));else
        if (mn(p)==mn(p << 1))
            se(p)=min(se(p << 1),mn(p << 1 | 1)); else
            se(p)=min(mn(p << 1),se(p << 1 | 1));
    }
    void modify1(int p,int l,int r,int x,int y,ll z)
    {
        if (l==x && r==y)
        {
            push_tag(p,z,z);
            return;
        }
        push_down(p);
        int mid(l+r >> 1);
        if (y<=mid)
            modify1(p << 1,l,mid,x,y,z); else
        if (x>mid)
            modify1(p << 1 | 1,mid+1,r,x,y,z); else
            {
                modify1(p << 1,l,mid,x,mid,z);
                modify1(p << 1 | 1,mid+1,r,mid+1,y,z);
            }
        update(p);
    }
    void modify2(int p,int l,int r,int x,int y,ll z)
    {
        if (l==x && r==y)
        {
            if (mn(p)>=z)
                return;
            if (l==r)
            {
                mn(p)=z;
                se(p)=INF;
                tag1(p)=tag2(p)=0;
            } else
            if (se(p)>z)
                push_tag(p,z-mn(p),0); else
                {
                    push_down(p);
                    int mid(l+r >> 1);
                    modify2(p << 1,l,mid,x,mid,z);
                    modify2(p << 1 | 1,mid+1,r,mid+1,y,z);
                    update(p);
                }
            return;
        }
        push_down(p);
        int mid(l+r >> 1);
        if (y<=mid)
            modify2(p << 1,l,mid,x,y,z); else
        if (x>mid)
            modify2(p << 1 | 1,mid+1,r,x,y,z); else
            {
                modify2(p << 1,l,mid,x,mid,z);
                modify2(p << 1 | 1,mid+1,r,mid+1,y,z);
            }
        update(p);
    }
    ll calc(int p,int l,int r,int x)
    {
        if (l==r)
            return mn(p);
        push_down(p);
        int mid(l+r >> 1);
        if (x<=mid)
            return calc(p << 1,l,mid,x); else
            return calc(p << 1 | 1,mid+1,r,x);
    }
}s2;
struct ask
{
    int opt;
    ll t;
    int c,z;
    ask () {}
    ask (int o,ll T,int C,int Z=0):opt(o),t(T),c(C),z(Z) {}
};
vector<ask>e[N];
#undef s
#define ls(p) a[p].ch[0]
#define rs(p) a[p].ch[1]
#define rk(p) a[p].Rk
#define tim(p) a[p].Tim
#define val(p) a[p].Val
#define id(p) a[p].Id
#define s(p) a[p].S
struct node3
{
    int ch[2],Rk,Tim,Val,Id;
    ll S;
};
int ct(0);
struct fhq_treap
{
    node3 a[N];
    int newnode(int x,int y,int z)
    {
        ++ct;
        ls(ct)=rs(ct)=0,rk(ct)=rand(),tim(ct)=x,val(ct)=y,id(ct)=z;
        s(ct)=y;
        return ct;
    }
    void update(int p)
    {
        s(p)=s(ls(p))+s(rs(p))+val(p);
    }
    void split(int &x,int &y,int rt,int k)
    {
        if (!rt)
        {
            x=y=0;
            return;
        }
        if (tim(rt)<=k)
        {
            x=rt;
            split(rs(rt),y,rs(rt),k);
        } else
        {
            y=rt;
            split(x,ls(rt),ls(rt),k);
        }
        update(rt);
    }
    int combine(int x,int y)
    {
        if (!x || !y)
            return x|y;
        if (rk(x)<rk(y))
        {
            rs(x)=combine(rs(x),y);
            update(x);
            return x;
        } else
        {
            ls(y)=combine(x,ls(y));
            update(y);
            return y;
        }
    }
}T;
int main()
{
    srand(time(NULL));
    scanf("%d%d%d",&n,&m,&q);
    s2.build(1,1,n);
    for (int i=1;i<=q;++i)
    {
        scanf("%d",&opt);
        if (opt==1)
        {
            scanf("%d%d%d%d",&l,&r,&c,&k);
            e[l].push_back(ask(1,k,c,i));
            e[r+1].push_back(ask(-1,k,c,i));
            s1.modify(1,1,n,l,r,k);
            s2.modify1(1,1,n,l,r,k);
        } else
        if (opt==2)
        {
            scanf("%d%d%d",&l,&r,&k);
            s2.modify1(1,1,n,l,r,-k);
            s2.modify2(1,1,n,1,n,0);
        } else
        {
            scanf("%d%lld",&c,&b),++cg;
            ll g(s2.calc(1,1,n,c));
            if (g<b)
                ans[cg]=0; else
                e[c].push_back(ask(0,s1.calc(1,1,n,c)-(g-b),cg));
        }
    }
    for (int i=1;i<=n;++i)
    {
        for (IT it=e[i].begin();it!=e[i].end();++it)
        {
            int opt(it->opt);
            ll t(it->t);
            int c(it->c),tz(it->z);
            if (opt==0)
            {
                int g(rt);
                for (;;)
                {
                    if (T.s(T.ls(g))>=t)
                        g=T.ls(g); else
                    if (T.s(T.ls(g))+T.val(g)>=t)
                    {
                        ans[c]=T.id(g);
                        break;
                    } else
                        t-=T.s(T.ls(g))+T.val(g),g=T.rs(g);
                }
            } else
            if (opt==1)
            {
                T.split(x,y,rt,tz);
                rt=T.combine(T.combine(x,T.newnode(tz,t,c)),y);
            } else
            {
                T.split(x,y,rt,tz);
                T.split(x,z,x,tz-1);
                rt=T.combine(x,y);
            }
        }
    }
    for (int i=1;i<=cg;++i)
        printf("%d\n",ans[i]);
    return 0;
}
posted @ 2021-04-18 16:14  GK0328  阅读(207)  评论(0编辑  收藏  举报