您的位置:首页 > 其它

【UOJ #218. 【UNR #1】】火车管理 可持久化线段树

2016-07-19 15:35 204 查看
题目:

uoj 旗下有一个火车站,用来管理属于 uoj 的小火车。

火车站一共有 n

n

条编号为 1,…,n

1,…,n

的,只有一端的用来存放小火车的铁路,由于小火车特殊的构造,每条铁路可以停放无数辆小火车。每条铁路是相互独立的。

铁路是一个栈结构,后停放的小火车可以先出来。

每辆小火车有一个吨位 t

t



由于 NOI2016 即将到来,想要跟小火车正面作战的人多了起来,火车站管理员九条可怜每天需要处理很多事件。

事件可以概括成一下三种:

•1 l r 有人想跟铁路编号在 [l,r]

[l,r]

的每条铁路的第一辆可以开出来的小火车正面战斗,你需要统计这些小火车的吨位之和,没有火车的铁路不计入答案。

•2 l 编号为 l

l

的铁路开走一辆火车,如果这条铁路没有小火车则不开出。

•3 l r x 铁路编号在 [l,r]

[l,r]

的每条铁路都新停放一辆吨位为 x

x

的火车。

现在管理员九条可怜要去南海前线了,你需要替他管理火车站。

由于火车站很忙,所以你需要实时反馈信息,我们会用一些手段要求你强制在线,具体请看输入格式。

输入格式

输入第一行三个非负整数 n,m,ty

n,m,ty

表示铁路的数量和操作次数还有是否强制在线。

接下来 m

m

行,每行四个数或者三个数或者两个数表示一次操作。

为了实时反馈信息,你需要解密 l,r

l,r

,设读入的是 l1,r1

l1,r1

,则实际的值如下:

l2r2lr====(l1+lastans⋅ty)modn+1(r1+lastans⋅ty)modn+1min(l2,r2)max(l2,r2)

l2=(l1+lastans⋅ty)modn+1r2=(r1+lastans⋅ty)modn+1l=min(l2,r2)r=max(l2,r2)

lastans

lastans

表示上一次询问的答案,如果之前没有询问则为 0

0



当你进行的是第二类操作时,只需要令 l=(l1+lastans⋅ty)modn+1

l=(l1+lastans⋅ty)modn+1

即可。

输入数据保证 1≤l1,r1≤n

1≤l1,r1≤n



注意,我们并没有加密吨位和操作类型

输出格式

对于每个询问输出一行,一个非负整数表示答案。

样例一

input

10 10 0

3 1 5 3

1 1 6

3 1 7 1

1 1 9

1 1 6

3 1 5 2

1 3 6

1 3 9

3 1 7 6

2 1

output

15

7

6

7

8

http://uoj.ac/problem/218

题解:

我们可以针对时间建立一颗可持久化线段树,维护每个铁路每个时间的栈顶的吨位和栈顶火车的入栈时间。

我们再维护一颗线段树用来统计答案。

于是操作就只有三种了:

区间询问:直接在答案线段树里询问即可。

区间压数:在可持久化线段树上进行区间覆盖,然后在答案线段树上修改一下。

单点弹数:由于我们记录了入栈时间,查询到入站时间t后,我们可以查询t时刻前的树,查出当前点入栈之前的栈顶的信息,然后在答案线段树上和可持久化线段树上修改。

代码

#include<iostream>
#include<stdio.h>
#include<string.h>
#define N 500005
#define lson id*2
#define rson id*2+1
using namespace std;
int n,m,sum[N*4],lazy[N*4];

void pd(int id,int l,int r,int mid)
{
if(lazy[id]==-1) return ;
sum[lson]=(mid-l+1)*lazy[id];
sum[rson]=(r-mid)*lazy[id];
lazy[lson]=lazy[rson]=lazy[id];
lazy[id]=-1;
}
void add(int id,int L,int R,int l,int r,int v)
{
//cout<<L<<"  "<<R<<"  "<<l<<" "<<r<<endl;
if(L>r||R<l) return ;
if(L>=l&&R<=r)
{
lazy[id]=v;
sum[id]=(R-L+1)*v;
return ;
}
int mid=(L+R)>>1;
pd(id,L,R,mid);
add(lson,L,mid,l,r,v);
add(rson,mid+1,R,l,r,v);
sum[id]=sum[lson]+sum[rson];
}
int getans(int id,int L,int R,int l,int r)
{
if(L>r||R<l) return 0;
if(L>=l&&R<=r) return sum[id];
int mid=(L+R)>>1;
pd(id,L,R,mid);
int ret=getans(lson,L,mid,l,r)+getans(rson,mid+1,R,l,r);
return ret;
}

int tim[N*75],val[N*75],tot,ls[N*75],rs[N*75];
int rt
;

void down(int id)
{
if(tim[id]==-1) return;
++tot;tim[tot]=tim[id];ls[tot]=ls[ls[id]];rs[tot]=rs[ls[id]];ls[id]=tot;val[tot]=val[id];
++tot;tim[tot]=tim[id];ls[tot]=ls[rs[id]];rs[tot]=rs[rs[id]];rs[id]=tot;val[tot]=val[id];
tim[id]=-1;
}
void build(int pre,int &now,int L,int R,int l,int r,int t,int v)
{
now=++tot;

if(L>=l&&R<=r)
{
tim[now]=t;
val[now]=v;
return ;
}   //cout<<L<<"   "<<R<<"           "<<l<<" "<<r<<endl;
if(pre) down(pre);
ls[now]=ls[pre],rs[now]=rs[pre];
int mid=(L+R)>>1;
if(mid>=l) build(ls[pre],ls[now],L,mid,l,r,t,v);
if(mid+1<=r) build(rs[pre],rs[now],mid+1,R,l,r,t,v);
}
int get(int id,int l,int r,int pos)
{
if(!id||tim[id]!=-1) return id;
int mid=(l+r)>>1;
if(pos<=mid) return get(ls[id],l,mid,pos);
return get(rs[id],mid+1,r,pos);

}
void del(int x,int y)
{
int id=get(rt[y-1],1,n,x);
if(!id)
{
rt[y]=rt[y-1];
return ;
}
//  if(tim[id]==0) while(1);
id=get(rt[tim[id]-1],1,n,x);
build(rt[y-1],rt[y],1,n,x,x,tim[id],val[id]);
add(1,1,n,x,x,val[id]);
}
void change(int l,int r,int v,int i)
{
build(rt[i-1],rt[i],1,n,l,r,i,v);

add(1,1,n,l,r,v);
}
int ty;
int ans;
int main()
{
scanf("%d%d%d",&n,&m,&ty);
memset(lazy,-1,sizeof(lazy));
memset(tim,-1,sizeof(tim));
for(int i=1,aa,bb,cc,dd;i<=m;i++)
{

scanf("%d",&aa);

if(aa==1)
{
scanf("%d%d",&bb,&cc);
bb=(bb+ans*ty)%n+1;
cc=(cc+ans*ty)%n+1;
if(bb>cc) swap(bb,cc);
ans=getans(1,1,n,bb,cc);
printf("%d\n",ans);
rt[i]=rt[i-1];
}
else if(aa==2)
{
scanf("%d",&bb);
bb=(bb+ans*ty)%n+1;
del(bb,i);
}
else if(aa==3)
{
scanf("%d%d%d",&bb,&cc,&dd);
bb=(bb+ans*ty)%n+1;
cc=(cc+ans*ty)%n+1;
if(bb>cc) swap(bb,cc);
change(bb,cc,dd,i);
}
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: