题意:
In 2016, Sister Jiayuan fell in love with the sequence of numbers. So he often studies some strange questions about sequences, and now he is studying a difficult problem
And need you to help him. The problem is this: Given a full permutation of 1 to n, now perform m local sorts on this full permutation sequence.
The order is divided into two types: 1: (0, l, r) means to sort the numbers of the interval [l, r] in ascending order 2: (1, l, r) means to sort the numbers of the interval [l, r] in descending order and finally ask Q
The number on the position.
The first line of input data is two integers n and m. n represents the length of the sequence, and m represents the number of partial sorts. 1 <= n, m <= 10 ^ 5 the second line is n integers
Number, representing a full permutation from 1 to n. Next enter m lines, each line has three integers op, l, r, op is 0 for ascending order, op is 1 for descending order
Sorting, l, r represents the sorted interval. Finally enter an integer q, where q is the position to ask after sorting, 1 <= q <= n. 1 <= n <= 10 ^ 5
, 1 <= m <= 10 ^ 5
The output data has only one line, an integer, which represents the number at the q position after all parts are sorted in order.
二分答案
假设现在要判断的是第 \(mid\) 位置的数
那么我们把数组中 \(\le a_{mid}\) 的数都标记成 0,\(>a_{mid}\) 的标记成 1,\(a\) 是数组
现在区间排序操作就简单了,数一下区间内有多少个 1 记为 \(s\)
如果是升序那就把区间右边 \(s\) 个位置区间赋值成 1,左边的区间赋值成 0
降序就把左边 \(s\) 个位置区间赋值成 1,右边的区间赋值成 0
最后操作完后判断一下第 \(mid\) 个数的标记
如果是 0 ,说明当前这个位置在操作完后的值 \(\le a_{mid}\) ,所以记录一下答案然后缩小右边界继续二分
如果是 1 ,说明当前这个位置在操作完后的值 \(>a_{mid}\),所以要缩小左边界
时间复杂度 \(O(n\log^2n)\)
// This code writed by chtholly_micromaker(MicroMaker)
#include <bits/stdc++.h>
#define reg register
using namespace std;
const int MaxN=100050;
struct Quetion
{
int opt,l,r;
}Q[MaxN];
template <class t> inline void read(t &s)
{
s=0;
reg int f=1;
reg char c=getchar();
while(!isdigit(c))
{
if(c=='-')
f=-1;
c=getchar();
}
while(isdigit(c))
s=(s<<3)+(s<<1)+(c^48),c=getchar();
s*=f;
return;
}
// number of 1
int val[MaxN<<2],lazy[MaxN<<2];
int a[MaxN];
int n,m;
#define lson (u<<1)
#define rson (u<<1|1)
inline void pushup(int u)
{
val[u]=val[lson]+val[rson];
return;
}
inline void pushdown(int u,int l,int r)
{
if(lazy[u]!=-1)
{
reg int mid=(l+r)>>1;
lazy[lson]=lazy[u];
lazy[rson]=lazy[u];
val[lson]=lazy[u]*(mid-l+1);
val[rson]=lazy[u]*(r-mid);
lazy[u]=-1;
}
return;
}
inline void buildtr(int u,int l,int r,int std)
{
if(l==r)
{
val[u]=(a[l]<=std?0:1);
return;
}
reg int mid=(l+r)>>1;
buildtr(lson,l,mid,std);
buildtr(rson,mid+1,r,std);
pushup(u);
return;
}
inline void modify(int u,int l,int r,int ql,int qr,int k)
{
if(ql>qr)
return;
if(ql<=l&&r<=qr)
{
lazy[u]=k;
val[u]=k*(r-l+1);
return;
}
pushdown(u,l,r);
reg int mid=(l+r)>>1;
if(ql<=mid)
modify(lson,l,mid,ql,qr,k);
if(mid<qr)
modify(rson,mid+1,r,ql,qr,k);
pushup(u);
return;
}
/*
inline int query(int u,int l,int r,int kth)
{
pushdown(u,l,r);
if(l==r)
return val[u];
reg int mid=(l+r)>>1;
if(kth<=val[lson])
return query(lson,l,mid,kth);
else
return query(rson,mid+1,r,kth-val[lson]);
return -1;
}
*/
inline int query(int u,int l,int r,int ql,int qr)
{
if(ql<=l&&r<=qr)
return val[u];
pushdown(u,l,r);
reg int mid=(l+r)>>1,ans=0;
if(ql<=mid)
ans+=query(lson,l,mid,ql,qr);
if(mid<qr)
ans+=query(rson,mid+1,r,ql,qr);
return ans;
}
inline void print()
{
puts("-=======-=-=-=-=-=-=-=");
puts("segtree");
for(int i=1;i<=n;++i)
printf("%d ",query(1,1,n,i,i));
puts("\n-======-=-=-=-=-=-\n");
}
inline void Init(int guess)
{
memset(val,0,sizeof val);
memset(lazy,-1,sizeof lazy);
buildtr(1,1,n,guess);
// puts("nyanpass~");
// puts("in the beginning");
// print();
for(int i=1;i<=m;++i)
{
/*
if(guess==25000&&i>=47110)
{
printf("Step #%d:\n",i);
printf("[ %d , %d ] option %d\n",Q[i].l,Q[i].r,Q[i].opt);
}*/
reg int mid=(Q[i].l+Q[i].r)>>1;
if(!Q[i].opt)
{
reg int x=query(1,1,n,Q[i].l,Q[i].r);
if(x>(Q[i].r-mid))
{
/*
if(guess==25000&&i>=47110)
{
puts("QAQ");
printf("%d %d\n",Q[i].l,mid-(x-(Q[i].r-mid)));
}
*/
modify(1,1,n,mid+1,Q[i].r,1);
modify(1,1,n,mid+1-(x-(Q[i].r-mid)),mid,1);
modify(1,1,n,Q[i].l,mid-(x-(Q[i].r-mid)),0);
// if(guess==25000&&i>=47110) puts("sss");
}
else if(x)
modify(1,1,n,Q[i].r-x+1,Q[i].r,1),
modify(1,1,n,Q[i].l,Q[i].r-x,0);
}
else
{
reg int x=query(1,1,n,Q[i].l,Q[i].r);
if(x>(mid-Q[i].l+1))
{
modify(1,1,n,Q[i].l,mid,1);
modify(1,1,n,mid+1,mid+x-(mid-Q[i].l+1),1);
modify(1,1,n,mid+1+x-(mid-Q[i].l+1),Q[i].r,0);
}
else if(x)
modify(1,1,n,Q[i].l,Q[i].l+x-1,1),
modify(1,1,n,Q[i].l+x,Q[i].r,0);
}
// print();
}
return;
}
signed main(void)
{
// freopen("D.in","r",stdin);
// freopen("D-成段更新.out","w",stdout);
cin>>n>>m;
for(int i=1;i<=n;++i)
read(a[i]);
for(int i=1;i<=m;++i)
{
read(Q[i].opt);read(Q[i].l);read(Q[i].r);
}
reg int q;cin>>q;
reg int l=1,r=n,ans=-1,mid;
/*
for(int i=1;i<=n;++i)
{
printf("[[[[TEST]]]] %d\n",i);
Init(i);
print();
}
*/
while(l<=r)
{
mid=(l+r)>>1;
// printf("lb: lr %d %d mid %d\n",l,r,mid);
Init(mid); // 0 <= 1 >
// print();
if(query(1,1,n,q,q))
l=mid+1;
else
ans=mid,r=mid-1;
}
cout<<ans<<endl;
return 0;
}