Description
在2016年,佳媛姐姐喜欢上了数字序列。因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题,需要你来帮助他。这个难题是这样子的:给出一个1到n的全排列,现在对这个全排列序列进行m次局部排序,排序分为两种:1:(0,l,r)表示将区间[l,r]的数字升序排序2:(1,l,r)表示将区间[l,r]的数字降序排序最后询问第q位置上的数字。
Input
输入数据的第一行为两个整数n和m。n表示序列的长度,m表示局部排序的次数。1 <= n, m <= 10^5第二行为n个整数,表示1到n的一个全排列。接下来输入m行,每一行有三个整数op, l, r, op为0代表升序排序,op为1代表降序排序, l, r 表示排序的区间。最后输入一个整数q,q表示排序完之后询问的位置, 1 <= q <= n。1 <= n <= 10^5,1 <= m <= 10^5
Output
输出数据仅有一行,一个整数,表示按照顺序将全部的部分排序结束后第q位置上的数字。
Sample Input
6 3
1 6 2 5 3 4
0 1 4
1 3 6
0 2 4
3
Sample Output
5
分析
我们二分一个x,对于每一个比x小的数,我们就把他变为0,反之就把他变为1。
对于每一个排序操作,升序就是把0扔到前面,把1扔到后面,最后的结果就是答案,至于0和1拿线段树维护一下就好
代码
#include <bits/stdc++.h>
#define N 100100
struct NOTE
{
int sum,cover;
bool f;
}t[N * 5];
int Q[N][3];
int num[N];
int n,m,p;
void change(int p,int l,int r,int v)
{
t[p].sum = (v?0:r - l + 1);
t[p].cover = v;
t[p].f = true;
}
void down(int p,int l,int r)
{
int mid = (l + r) >> 1;
if (t[p].f)
{
change(p * 2,l,mid,t[p].cover);
change(p * 2 + 1,mid + 1,r,t[p].cover);
t[p].f = false;
}
}
void insert(int p,int l,int r,int x,int y,int v)
{
if (x > y)
return;
if (l == x && r == y)
{
change(p,l,r,v);
return;
}
down(p,l,r);
int mid = (l + r) >> 1;
if (y <= mid)
insert(p * 2,l,mid,x,y,v);
else
if (x > mid)
insert(p * 2 + 1,mid + 1,r,x,y,v);
else
{
insert(p * 2,l,mid,x,mid,v);
insert(p * 2 + 1,mid + 1,r,mid + 1,y,v);
}
t[p].sum = t[p * 2].sum + t[p * 2 + 1].sum;
}
int getSum(int p,int l,int r,int x,int y)
{
if (l == x && r == y)
return t[p].sum;
down(p,l,r);
int mid = (l + r) >> 1;
if (y <= mid)
return getSum(p * 2,l,mid,x,y);
else
if (x > mid)
return getSum(p * 2 + 1,mid + 1,r,x,y);
else return getSum(p * 2,l,mid,x,mid) + getSum(p * 2 + 1,mid + 1,r,mid + 1,y);
}
bool check(int x)
{
for (int i = 1; i <= n; i++)
if (num[i] < x)
insert(1,1,n,i,i,0);
else insert(1,1,n,i,i,1);
for (int i = 1; i <= m; i++)
{
int tot = getSum(1,1,n,Q[i][1],Q[i][2]);
if (Q[i][0])
{
insert(1,1,n,Q[i][1],Q[i][2] - tot,1);
insert(1,1,n,Q[i][2] - tot + 1,Q[i][2],0);
}
else
{
insert(1,1,n,Q[i][1],Q[i][1] + tot - 1,0);
insert(1,1,n,Q[i][1] + tot,Q[i][2],1);
}
}
return !getSum(1,1,n,p,p);
}
int main()
{
scanf("%d%d",&n,&m);
for (int i = 1; i <= n; i++)
scanf("%d",&num[i]);
for (int i = 1; i <= m; i++)
scanf("%d%d%d",&Q[i][0],&Q[i][1],&Q[i][2]);
scanf("%d",&p);
int l = 1, r = n;
while (l < r)
{
int mid = (l + r + 1) >> 1;
if (check(mid))
l = mid;
else r = mid - 1;
}
printf("%d\n",l);
}