zoukankan      html  css  js  c++  java
  • 【BZOJ4552】[Tjoi2016&Heoi2016]排序 二分+线段树

    【BZOJ4552】[Tjoi2016&Heoi2016]排序

    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

    题解:思路非常巧妙,先二分答案,然后将>=mid的位置看成1,其余看成0,然后排序就变成了将段区间的1全都放到左边或右边,这个用线段树很容易搞定。

    单调性也十分显然,如果原来的结果是1,那么在增加一个1后,结果不可能变为0;如果原来的结果是0,那么在去掉一个1后,结果不可能变为1。

     

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #define lson x<<1
    #define rson x<<1|1
    using namespace std;
    const int maxn=100010;
    int n,m,now,pos;
    
    int s[maxn<<2],tag[maxn<<2],pa[maxn],pb[maxn],op[maxn],v[maxn];
    inline int rd()
    {
    	int ret=0,f=1;	char gc=getchar();
    	while(gc<'0'||gc>'9')	{if(gc=='-')	f=-f;	gc=getchar();}
    	while(gc>='0'&&gc<='9')	ret=ret*10+gc-'0',gc=getchar();
    	return ret*f;
    }
    inline void pushdown(int l,int r,int x)
    {
    	if(tag[x]!=-1)
    	{
    		int mid=(l+r)>>1;
    		s[lson]=(mid-l+1)*tag[x],s[rson]=(r-mid)*tag[x],tag[lson]=tag[rson]=tag[x];
    		tag[x]=-1;
    	}
    }
    void build(int l,int r,int x)
    {
    	tag[x]=-1;
    	if(l==r)
    	{
    		s[x]=(v[l]>=now);
    		return ;
    	}
    	int mid=(l+r)>>1;
    	build(l,mid,lson),build(mid+1,r,rson);
    	s[x]=s[lson]+s[rson];
    }
    void updata(int l,int r,int x,int a,int b,int c)
    {
    	if(a>b)	return ;
    	if(a<=l&&r<=b)
    	{
    		s[x]=(r-l+1)*c,tag[x]=c;
    		return ;
    	}
    	pushdown(l,r,x);
    	int mid=(l+r)>>1;
    	if(a<=mid)	updata(l,mid,lson,a,b,c);
    	if(b>mid)	updata(mid+1,r,rson,a,b,c);
    	s[x]=s[lson]+s[rson];
    }
    int query(int l,int r,int x,int a,int b)
    {
    	if(a<=l&&r<=b)	return s[x];
    	pushdown(l,r,x);
    	int mid=(l+r)>>1;
    	if(b<=mid)	return query(l,mid,lson,a,b);
    	if(a>mid)	return query(mid+1,r,rson,a,b);
    	return query(l,mid,lson,a,b)+query(mid+1,r,rson,a,b);
    }
    bool check()
    {
    	build(1,n,1);
    	int i,a;
    	for(i=1;i<=m;i++)
    	{
    		a=query(1,n,1,pa[i],pb[i]);
    		if(op[i])	updata(1,n,1,pa[i],pa[i]+a-1,1),updata(1,n,1,pa[i]+a,pb[i],0);
    		else	updata(1,n,1,pa[i],pb[i]-a,0),updata(1,n,1,pb[i]-a+1,pb[i],1);
    	}
    	return query(1,n,1,pos,pos);
    }
    int main()
    {
    	n=rd(),m=rd();
    	int i,l=1,r=n+1;
    	for(i=1;i<=n;i++)	v[i]=rd();
    	for(i=1;i<=m;i++)	op[i]=rd(),pa[i]=rd(),pb[i]=rd();
    	pos=rd();
    	while(l<r)
    	{
    		now=(l+r)>>1;
    		if(check())	l=now+1;
    		else	r=now;
    	}
    	printf("%d",l-1);
    	return 0;
    }

     

  • 相关阅读:
    [leetcode]34.Find First and Last Position of Element in Sorted Array找区间
    [leetcode]278. First Bad Version首个坏版本
    [leetcode]367. Valid Perfect Square验证完全平方数
    [leetcode]45. Jump Game II青蛙跳(跳到终点最小步数)
    [leetcode]55. Jump Game青蛙跳(能否跳到终点)
    [leetcode]26. Remove Duplicates from Sorted Array有序数组去重(单个元素只出现一次)
    [leetcode]27. Remove Element删除元素
    [leetcode]20. Valid Parentheses有效括号序列
    [leetcode]15. 3Sum三数之和
    C#中的局部类型
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7671126.html
Copyright © 2011-2022 走看看