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

来源:互联网 发布:域名注册量查询 编辑:程序博客网 时间:2024/05/16 20:39

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

#include<iostream>#include<algorithm>#include<stdio.h>#include<string.h>#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);        }    }}
0 0
原创粉丝点击