【uoj218】火车管理 题解&代码(C++)

题目链接:
http://uoj.ac/problem/218
题解:
我们可以针对时间建立一颗可持久化线段树,维护每个铁路每个时间的栈顶的吨位和栈顶火车的入栈时间。
我们再维护一颗线段树用来统计答案。
于是操作就只有三种了:
区间询问:直接在答案线段树里询问即可。
区间压数:在可持久化线段树上进行区间覆盖,然后在答案线段树上修改一下。
单点弹数:由于我们记录了入栈时间,查询到入站时间t后,我们可以查询t时刻前的树,查出当前点入栈之前的栈顶的信息,然后在答案线段树上和可持久化线段树上修改。
具体看代码,题解也是在uoj官方题解上略作修改2333
代码:

#include
#include
#include
#include
#define lson id*2
#define rson id*2+1
#define maxn (500005)
using namespace std;
//统计答案的线段树 
int n,m,py,ans,sum[maxn*8],lazy[maxn*8];
void pushdown1(int id,int l,int r)
{
    if (lazy[id]==-1) return ;
    int mid=(r+l)>>1;int v=lazy[id];lazy[id]=-1;
    sum[lson]=(mid-l+1)*v;sum[rson]=(r-mid)*v;
    lazy[lson]=lazy[rson]=v;
}
void fff(int id,int l,int r,int L,int R,int v)
{
    if (l>r||L>R) return ;
    if (l>=L&&r<=R) {sum[id]=(r-l+1)*v;lazy[id]=v;return ;}
    int mid=(l+r)>>1;pushdown1(id,l,r);
    if (mid>=L) fff(lson,l,mid,L,R,v);
    if (mid+1<=R) fff(rson,mid+1,r,L,R,v);
    sum[id]=sum[lson]+sum[rson];
}
int query(int id,int l,int r,int L,int R)
{
    if (l>r||L>R) return 0;int cnt=0;
    if (l>=L&&r<=R) {
    return sum[id];}
    int mid=(l+r)>>1;pushdown1(id,l,r);
    if (mid>=L) cnt+=query(lson,l,mid,L,R);
    if (mid+1<=R) cnt+=query(rson,mid+1,r,L,R); 
    return cnt;
}
//对时间建可持久化线段树
int tim[maxn*75],val[maxn*75],ls[maxn*75],rs[maxn*75],root[maxn],tot;
void pushdown2(int id)
{
    if (tim[id]==-1) return ;
    tot++;ls[id]=tot;tim[tot]=tim[id];val[tot]=val[id];
    tot++;rs[id]=tot;tim[tot]=tim[id];val[tot]=val[id];
    tim[id]=-1;
}
void build(int pre,int &now,int l,int r,int L,int R,int i,int v)
{
    tot++;now=tot;
    if (l>r||L>R) return ; 
    if (L<=l&&r<=R){tim[now]=i;val[now]=v;return ;}
    if (pre) pushdown2(pre);
    ls[now]=ls[pre];rs[now]=rs[pre];
    tim[now]=tim[pre];val[now]=val[pre];
    int mid=(l+r)>>1;
    if (L<=mid) build(ls[pre],ls[now],l,mid,L,R,i,v);
    if (R>=mid+1) build(rs[pre],rs[now],mid+1,r,L,R,i,v);
}
int getans(int id,int l,int r,int x)
{
    if (tim[id]!=-1||id==0) return id;
    int mid=(l+r)>>1;
    if (mid>=x) return getans(ls[id],l,mid,x);
    if (x>=mid+1) return getans(rs[id],mid+1,r,x);
}
void del(int x,int i)
{
    int id=getans(root[i-1],1,n,x);
    if (id==0) {root[i]=root[i-1];return ;}
    int tmp=getans(root[tim[id]-1],1,n,x);
    build(root[i-1],root[i],1,n,x,x,tim[tmp],val[tmp]);
    fff(1,1,n,x,x,val[tmp]);
}
void add(int l,int r,int v,int i)
{
    build(root[i-1],root[i],1,n,l,r,i,v);
    fff(1,1,n,l,r,v);
}
int main()
{
    memset(lazy,-1,sizeof(lazy));
    memset(tim,-1,sizeof(tim));
    scanf("%d%d%d",&n,&m,&py);
    for (int i=1,l,r,tp,v;i<=m;i++)
    {
        scanf("%d",&tp);
        if (tp==1)
        {
            scanf("%d%d",&l,&r);
            l=(l+ans*py)%n+1;
            r=(r+ans*py)%n+1;
            if (l>r) swap(l,r);
            ans=query(1,1,n,l,r);
            printf("%d\n",ans);
            root[i]=root[i-1];
        }
        if (tp==2)
        {
            scanf("%d",&l);
            l=(l+ans*py)%n+1;
            del(l,i);
        }
        if (tp==3)
        {
            scanf("%d%d%d",&l,&r,&v);
            l=(l+ans*py)%n+1;
            r=(r+ans*py)%n+1;
            if (l>r) swap(l,r); 
            add(l,r,v,i);
        }
    }
}

你可能感兴趣的:(oi之路,uoj,线段树,数据结构,可持久化)