AFO

[HEOI2016/TJOI2016]排序

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

[Submit][Status][Discuss]


二分+线段树
两个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));
}
posted @ 2018-10-26 11:51  ZUTTER☮  阅读(134)  评论(0编辑  收藏  举报