题目链接:
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);
}
}
}