暂无链接
玩
题目背景
你的昆特牌打的太好啦!不一会你就 A K AK AK 了 N O G P NOGP NOGP,只能无聊地堆牌玩!
题面描述
你有一些矩形卡牌,每次你会作如下三个操作:
1.紧挨着最后一张牌往牌后面放一张牌,这张牌的底边与
X
X
X 轴重合且位于第一象限;(第一张牌最左边位于
X
=
0
X=0
X=0 处)
2.拿走一张牌,并把后面的牌向前推到与前一张牌右边重合;
3.询问
[
l
,
r
]
[l , r]
[l,r](坐标)这一段牌最高的高度;
对于边界情况,在两张牌交界处视为最高的那张牌的高度。
输入输出可能需要加速!
输入数据
第一行两个数
N
、
C
N、C
N、C 表示操作数、离线操作还是在线;
接下来 N 行每行是如下三种之一
T
=
1
T=1
T=1,接下来
L
E
N
、
H
LEN、H
LEN、H 分别表示插入的牌的长、高;
T
=
2
T=2
T=2,接下来
X
X
X 表示拿走哪一张牌,牌的编号按出现顺序由小到大,从
1
1
1 开始(不是操
作序号!),删除的牌不会改变序号,若序号表示的牌已被删除则不操作;
T
=
3
T=3
T=3,接下来 L、R 表示询问区间;若询问区间上没牌,输出 0。
若
C
=
1
C=1
C=1,则上面输入中的
L
E
N
、
H
LEN、H
LEN、H(仅这两项!)需要以下式子算出(
l
a
s
t
a
n
s
lastans
lastans 为最近一次询问答案,初值为
0
0
0)
真
实
输
入
=
(
输
入
∗
2333
+
l
a
s
t
a
n
s
∗
666
)
%
100000007
+
1
;
(
1
e
8
+
7
!
)
真实输入 = (输入*2333 + lastans*666 ) \%100000007+1; (1e8+7!)
真实输入=(输入∗2333+lastans∗666)%100000007+1;(1e8+7!)
输出数据
对每一个询问操作输出该段最高的位置高度是多少。
样例数据
INPUT
6 0
1 5 3
1 8 2
3 2 6
1 2 4
2 2
3 2 6
OUTPUT
3
4
样例解释
注意拿走一张牌时要把后面的牌向前推;
对于样例前三次操作的图像
红色线条表示询问区间
数据范围
对于
40
%
40\%
40%的数据,没有删除操作;
对于额外
20
%
20\%
20%的数据,
C
=
0
C=0
C=0;
对于
80
%
80\%
80%的数据,
N
≤
2
∗
1
0
5
N≤2*10^5
N≤2∗105;
对于
100
%
100\%
100%的数据,
N
≤
5
∗
1
0
5
N≤5*10^5
N≤5∗105 ,
L
E
N
、
H
≤
1
0
9
LEN、H≤10^9
LEN、H≤109,
L
、
R
L、R
L、R 不会超过 1e18 范围,输入的没有负数。
TIPS
注意边界情况!
如这时最高点是左边的牌的高度!
一个我看来没什么问题的问题的补充:若
L
=
R
L=R
L=R,答案不为
0
0
0 哦
提前
A
K
AK
AK 的同学互相玩玩昆特牌吧!(雾)
强烈建议大家注意细节!
题解
很简单的一道线段树,以牌的标号建线段树,维护长度和与最高的高度,查询时在线段树上二分坐标所在牌的编号。
对于边界问题,查询的时候右边界加一即可。
代码
#include<bits/stdc++.h>
#define ll long long
#define ls v<<1
#define rs ls|1
#define F(x) (x*2333+last*666)%100000007+1
using namespace std;
const int M=2e6+5;
int mx[M],tag[M],tot,n,typ;
ll sum[M],r;
char c;
ll read()
{
for(r=0;!isdigit(c);c=getchar());
for(;isdigit(c);c=getchar())r=(r<<1)+(r<<3)+c-'0';
return r;
}
void out(int x)
{
if(x>9)out(x/10);
putchar(x%10+'0');
}
void up(int v)
{
sum[v]=sum[ls]+sum[rs];
mx[v]=max(mx[ls],mx[rs]);
}
void ins(int v,int le,int ri,int pos,int len,int h)
{
if(le==ri){sum[v]=len,mx[v]=h;return;}
int mid=le+ri>>1;
if(pos<=mid)ins(ls,le,mid,pos,len,h);
else ins(rs,mid+1,ri,pos,len,h);
up(v);
}
void del(int v,int le,int ri,int pos)
{
if(le==ri){sum[v]=mx[v]=0;return;}
int mid=le+ri>>1;
if(pos<=mid)del(ls,le,mid,pos);
else del(rs,mid+1,ri,pos);
up(v);
}
int get(int v,int le,int ri,ll pos)
{
if(le==ri){return le;}
int mid=le+ri>>1;
if(sum[ls]>=pos)return get(ls,le,mid,pos);
else return get(rs,mid+1,ri,pos-sum[ls]);
}
int ask(int v,int le,int ri,int lb,int rb)
{
if(lb<=le&&ri<=rb){return mx[v];}
int mid=le+ri>>1,ans=0;
if(lb<=mid)ans=ask(ls,le,mid,lb,rb);
if(mid<rb)ans=max(ans,ask(rs,mid+1,ri,lb,rb));
return ans;
}
void in(){n=read(),typ=read();}
void ac()
{
ll a,b,last=0;
for(int i=1,op;i<=n;++i)
{
op=read(),a=read();
if(op==1)
{
b=read();
if(typ)a=F(a),b=F(b);
ins(1,1,n,++tot,a,b);
}
else if(op==2)del(1,1,n,a);
else
{
b=read();
a=get(1,1,n,a),b=get(1,1,n,b+1);
out(last=ask(1,1,n,a,b)),putchar(10);
}
}
}
int main(){in(),ac();}