试题 历届真题 双向排序【第十二届】【省赛】【B组】
资源限制
内存限制:256.0MB C/C++时间限制:1.0s Java时间限制:3.0s Python时间限制:5.0s
分析:
一看题,对区间修改查询,想到线段树,但是如何定义状态呢?一开始想到维护差分,但是模拟了几次,发现没规律,然后又对着原数组模拟,发现如下规律:
1.数组就两个状态,前半段是降区间,后半段是升区间,考虑记录每个数是属于升区间还是降区间。用1 表示升区间,0表示降区间。
2.对每个有意义的操作(没意义的操作就是,例如输入0 5,但是前5个甚至前10个数都是降的,这个就是没意义的),无论是改成升序列 还是降序列,都是尽可能的改变小的,靠近1的值。这个可以自行模拟试一试,提示到这里了,希望读者能画一画。
上代码:
n,m=map(int,input().split())
class node():
def __init__(self,lazy=-1,sum=1):
self.lazy=lazy
self.sum=sum #对于叶子节点 1表示这个点在升序列 0在降序列 对于其他节点 sum记录了这个#区间的属于升序列的数的个数
tree=[node() for i in range(100000*4+100)]
def pushup(x):
tree[x].sum=tree[x<<1].sum+tree[(x<<1)+1].sum
def pushdown(x,l,r):
if (tree[x].lazy!=(-1)):
mid=(l+r)>>1
tree[x<<1].lazy=tree[x].lazy
tree[(x<<1)+1].lazy=tree[x].lazy
tree[x<<1].sum=tree[x].lazy*(mid-l+1)
tree[1+(x << 1)].sum = tree[x].lazy * (r-mid)
tree[x].lazy=-1
def build(x,l,r):
if (l==r):
return
mid=(l+r)>>1
build(2*x,l,mid)
build(2*x+1,mid+1,r)
pushup(x)
tree[x].lazy=-1
def update0(x,l,r,num): #将a1 到 am 降序 优先操作左端
if (num>=tree[x].sum): #我要将升序改成降序,如果要改的数量比全部的升序还多,直接全清空就好
tree[x].sum=0
tree[x].lazy=0
return
pushdown(x, l, r)
num_l1 = tree[x << 1].sum
mid = (l +r) >> 1
if num<=num_l1:
update0(2*x,l,mid,num)
else :
update0(2*x,l,mid,num_l1)
update0(2*x+1,mid+1,r,num-num_l1)
pushup(x)
def update1(x,l,r,num): #这是把降序变成升序,还是对左端优先处理
numx = (r - l + 1) - tree[x].sum
if (num>=numx):
tree[x].sum=r-l+1
tree[x].lazy=1
return
pushdown(x,l,r)
mid=(l+r)>>1
numl=(mid-l+1)-tree[x<<1].sum
if num<=numl:
update1(x*2,l,mid,num)
else:
update1(x*2,l,mid,numl)
update1(x*2+1,mid+1,r,num-numl)
pushup(x)
def query(x,l,r,i):
if (l==r):
return tree[x].sum
pushdown(x,l,r)
mid=(l+r)>>1
if (i<=mid):
return query(x*2,l,mid,i)
else:
return query(x*2+1,mid+1,r,i)
pre_i=1 #数组中升序列和降序列的分界,是升序列的第一个数
build(1,1,n)
for i in range(m):
p,q=map(int,input().split())
if (p): #增
if (pre_i<=q):
continue
update1(1,1,n,pre_i-q)
pre_i=q
else:
if pre_i>q:continue
update0(1,1,n,q-pre_i+1)
pre_i=q+1
s=[] #记录升序列
j=[] #降序列
for i in range(1,n+1):
if (query(1,1,n,i)):
s.append(i)
else:
j.append(i)
i=len(j)
while(i!=0):
print(j[i-1],end=" ")
i-=1
if (len(s)):
for i in range(len(s) - 1):
print(s[i], end=" ")
print(s[-1])
通过情况: