4552: [Tjoi2016&Heoi2016]排序
Time Limit: 60 Sec Memory Limit: 256 MBSubmit: 509 Solved: 291
[ Submit][ Status][ Discuss]
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
1 6 2 5 3 4
0 1 4
1 3 6
0 2 4
3
Sample Output
5
HINT
Source
二分答案为ans,然后将原序列做一些修改
把原序列中小于ans的数字全部替换成0,把原序列中大于等于ans的数字全部替换成1
这样每个操作都能用线段树实现了
最后检查位置Q是否为1即可==
复杂度O(nlog^2n)
第一发边界没判WA了。。。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 1E5 + 10;
const int T = 4;
int n,m,Q,s[2],a[maxn],b[maxn],sum[maxn*T][2]
,Mark[maxn*T],L[maxn],R[maxn],typ[maxn];
void Build(int o,int l,int r)
{
if (l == r)
{
sum[o][b[l]] = 1;
sum[o][b[l]^1] = 0;
Mark[o] = -1;
return;
}
Mark[o] = -1;
int mid = (l + r) >> 1;
Build(o<<1,l,mid);
Build(o<<1|1,mid+1,r);
for (int i = 0; i < 2; i++)
sum[o][i] = sum[o<<1][i] + sum[o<<1|1][i];
}
void pushdown(int o,int l,int r)
{
if (Mark[o] == -1) return;
int mid = (l + r) >> 1,len = r - l + 1;
sum[o][Mark[o]] = len; sum[o][Mark[o]^1] = 0;
if (l == r) {Mark[o] = -1; return;}
Mark[o<<1] = Mark[o];
Mark[o<<1|1] = Mark[o];
Mark[o] = -1;
}
void Modify(int o,int l,int r,int ml,int mr,int tp)
{
if (ml <= l && r <= mr)
{
Mark[o] = tp;
pushdown(o,l,r);
return;
}
pushdown(o,l,r);
int mid = (l + r) >> 1;
if (ml <= mid) Modify(o<<1,l,mid,ml,mr,tp); else pushdown(o<<1,l,mid);
if (mr > mid) Modify(o<<1|1,mid+1,r,ml,mr,tp); else pushdown(o<<1|1,mid+1,r);
for (int i = 0; i < 2; i++)
sum[o][i] = sum[o<<1][i] + sum[o<<1|1][i];
}
void Query(int o,int l,int r,int ql,int qr)
{
pushdown(o,l,r);
if (ql <= l && r <= qr)
{
for (int i = 0; i < 2; i++)
s[i] += sum[o][i];
return;
}
int mid = (l + r) >> 1;
if (ql <= mid) Query(o<<1,l,mid,ql,qr);
if (qr > mid) Query(o<<1|1,mid+1,r,ql,qr);
}
bool Judge(int now)
{
for (int i = 1; i <= n; i++)
b[i] = (a[i] >= now)?1:0;
Build(1,1,n);
for (int i = 1; i <= m; i++)
{
memset(s,0,sizeof(s));
Query(1,1,n,L[i],R[i]);
int len = R[i] - L[i] + 1;
if (!typ[i])
{
if (s[0])
Modify(1,1,n,L[i],L[i] + s[0] - 1,0);
if (s[0] < len)
Modify(1,1,n,L[i] + s[0],R[i],1);
}
else
{
if (s[1])
Modify(1,1,n,L[i],L[i] + s[1] - 1,1);
if (s[1] < len)
Modify(1,1,n,L[i] + s[1],R[i],0);
}
}
memset(s,0,sizeof(s));
Query(1,1,n,Q,Q);
return s[1];
}
int getint()
{
char ch = getchar();
int ret = 0;
while (ch < '0' || '9' < ch) ch = getchar();
while ('0' <= ch && ch <= '9')
ret = ret*10 + ch - '0',ch = getchar();
return ret;
}
int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
#endif
n = getint(); m = getint();
for (int i = 1; i <= n; i++) a[i] = getint();
for (int i = 1; i <= m; i++)
typ[i] = getint(),L[i] = getint(),R[i] = getint();
Q = getint();
int l = 1,r = n;
while (r - l > 1)
{
int mid = (l + r) >> 1;
if (Judge(mid)) l = mid;
else r = mid;
}
if (Judge(r)) cout << r;
else cout << l;
return 0;
}