4552: [Tjoi2016&Heoi2016]排序
Time Limit: 60 Sec Memory Limit: 256 MB
Submit: 2366 Solved: 1188
[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
Sample Output
5
Source
二分+线段树
两个log ==
然后就随便做啦
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define update(now) d[now]=d[now*2]+d[now*2+1]
#define LL long long
#define M 400001
#define max(a,b) ((a)>(b)? (a):(b))
#define min(a,b) ((a)<(b)? (a):(b))
using namespace std;
int i,m,n,h,j,k,d[M],a[M], s[M][3],q,maxx,b[M],lazy[M];
void down(int now,int l,int r)
{
if(!b[now]) return ;
int mid=(l+r)>>1;
d[now*2]=lazy[now]*(mid-l+1);
d[now*2+1]=lazy[now]*(r-mid);
lazy[now*2]=lazy[now*2+1]=lazy[now];
b[now*2]=b[now*2+1]=1;
b[now]=lazy[now]=0;
}
void built(int now,int l,int r,int z)
{
if(l==r)
{
if(a[l]>=z) d[now]=1;
else d[now]=0;
lazy[now]=b[now]=0;
return;
}
int mid=(l+r)>>1;
built(now*2,l,mid,z);
built(now*2+1,mid+1,r,z);
update(now);
}
void modify(int now,int l,int r,int ll,int rr,int z)
{
if(l>=ll && r<=rr)
{
d[now]=(r-l+1)*z;
lazy[now]=z;
b[now]=1;
return ;
}
down(now,l,r);
int mid=(l+r)>>1;
if(ll<=mid) modify(now*2,l,mid,ll,rr,z);
if(rr>mid) modify(now*2+1,mid+1,r,ll,rr,z);
update(now);
}
int find1(int now,int l,int r,int ll,int rr)
{
if(l>=ll && r<=rr) return d[now];
int mid=(l+r)>>1,ans=0;
down(now,l,r);
if(ll<=mid) ans+=find1(now*2,l,mid,ll,rr);
if(rr>mid) ans+=find1(now*2+1,mid+1,r,ll,rr);
return ans;
}
int find(int now,int l,int r,int w)
{
if(l==r) return d[now];
int mid=(l+r)>>1;
down(now,l,r);
if(w<=mid) return find(now*2,l,mid,w);
return find(now*2+1,mid+1,r,w);
}
bool check(int now)
{
for(int i=1;i<=m;i++)
{
int t=find1(1,1,n,s[i][1],s[i][2]);
if(!t) continue;
if(s[i][0])
{
modify(1,1,n,s[i][1]+t,s[i][2],0);
modify(1,1,n,s[i][1],s[i][1]+t-1,1);
}
else
{
modify(1,1,n,s[i][2]-t+1,s[i][2],1);
modify(1,1,n,s[i][1],s[i][2]-t,0);
}
}
return find(1,1,n,q);
}
int ef(int l,int r)
{
int mid=l,tmp=l;
while(r>=l)
{
mid=(l+r)>>1;
memset(b,0,sizeof(b));
memset(d,0,sizeof(d));
memset(lazy,0,sizeof(lazy));
built(1,1,n,mid);
if(check(mid)) tmp=mid, l=mid+1;
else r=mid-1;
}
return tmp;
}
int main()
{
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++) scanf("%d",&a[i]);
for(i=1;i<=m;i++) scanf("%d%d%d",&s[i][0],&s[i][1],&s[i][2]);
scanf("%d",&q);
printf("%d",ef(0,n));
}