Description
在2016年,佳媛姐姐喜欢上了数字序列。因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题,需要你来帮助他。
这个难题是这样子的:给出一个1到n的全排列,现在对这个全排列序列进行m次局部排序,排序分为两种:
- (0,l,r) 表示将区间 [l,r] 的数字升序排序
- (1,l,r) 表示将区间 [l,r] 的数字降序排序
最后询问第q位置上的数字。
Solution
暴力有60分!!!
然而,我们还是要AC
直接做很难做。能不能把每次排序的复杂度降下来?
可以二分答案(??是不是很奇怪)
然后对于原序列,把每个数减去二分的答案,得数大于0就是1,否则就是0。
然后排序就变成了区间修改0和1,可以用线段树维护。最后只需要查询位置上的值是0还是1来调整二分。
Code
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iostream>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fod(i,a,b) for(i=a;i>=b;i--)
struct note
{
int ls,rs,sm;
}tree[1000005];
using namespace std;
int a[100005],n,m,cz[100005][3],q,lazy[1000005],num;
bool cmp(int x,int y)
{
return x>y;
}
void build(int now,int l,int r,int v)
{
if (l==r)
{
tree[now].sm=(a[l]-v>=0)?1:0;
return;
}
int mid=(l+r)/2;
tree[now].ls=++num;
build(num,l,mid,v);
tree[now].rs=++num;
build(num,mid+1,r,v);
tree[now].sm=tree[tree[now].ls].sm+tree[tree[now].rs].sm;
}
void down(int now,int l,int mid,int r)
{
int ls=tree[now].ls,rs=tree[now].rs;
if (lazy[now]!=-1)
{
tree[ls].sm=(mid-l+1)*lazy[now];
tree[rs].sm=(r-mid)*lazy[now];
lazy[ls]=lazy[rs]=lazy[now];
lazy[now]=-1;
}
}
void change(int now,int l,int r,int x,int y,int v)
{
if (x>y) return;
if (l==x&&r==y)
{
tree[now].sm=v*(r-l+1);
lazy[now]=v;
return;
}
int ls=tree[now].ls,rs=tree[now].rs,mid=(l+r)/2;
down(now,l,mid,r);
if(y<=mid) change(ls,l,mid,x,y,v);
else if(x>mid) change(rs,mid+1,r,x,y,v);
else
{
change(ls,l,mid,x,mid,v);
change(rs,mid+1,r,mid+1,y,v);
}
tree[now].sm=tree[ls].sm+tree[rs].sm;
}
int find(int now,int l,int r,int x,int y)
{
if (l==x&&r==y) return tree[now].sm;
int ls=tree[now].ls,rs=tree[now].rs,mid=(l+r)/2,s;
down(now,l,mid,r);
if (y<=mid) s=find(ls,l,mid,x,y);
else if (x>mid) s=find(rs,mid+1,r,x,y);
else s=find(ls,l,mid,x,mid)+find(rs,mid+1,r,mid+1,y);
tree[now].sm=tree[ls].sm+tree[rs].sm;
return s;
}
int pd(int k)
{
num=1;
memset(lazy,255,sizeof(lazy));
build(1,1,n,k);
int i;
fo(i,1,m)
{
int p=cz[i][0],x=cz[i][1],y=cz[i][2];
int t=find(1,1,n,x,y);
if (p)
{
change(1,1,n,x,x+t-1,1);
change(1,1,n,x+t,y,0);
}
else
{
change(1,1,n,x,y-t,0);
change(1,1,n,y-t+1,y,1);
}
}
return find(1,1,n,q,q);
}
int main()
{
freopen("sort.in","r",stdin);
cin>>n>>m;
int i,j;
fo(i,1,n) scanf("%d",&a[i]);
int l=1,r=n;
fo(i,1,m) scanf("%d%d%d",&cz[i][0],&cz[i][1],&cz[i][2]);
cin>>q;
while (l<r-1)
{
int mid=(l+r)/2;
if (pd(mid)==1) l=mid;
else r=mid;
}
int s;
if (pd(l)==1) s=l;
else s=r;
cout<<s;
}