首页 > 其他分享 >P2824 [HEOI2016/TJOI2016] 排序

P2824 [HEOI2016/TJOI2016] 排序

时间:2023-10-02 21:55:39浏览次数:38  
标签:rt cur int P2824 mid lt TJOI2016 HEOI2016 qx

针对区间排序,显然能够上值域线段树类似,但这里有个更强的做法。
如果能转化成01序列,那么一个区间排序的时候,只需区间询问1的个数+区间修改就可以了。
因为是排列,很清晰的二分一个mid,把大于等于它的设为1,小于它的设为0,再跑上面的算法,最后check一下询问位置是否为1即可。
单调性?感性理解,假设 \(mid1<mid2\) 且 \(mid2\) 返回的是true,那么 \(mid1\) 只会让限制更加宽泛,所以一定返回的是true,那么一定能找到一个 \(mid\) 使得它和它前面的返回是true,它后面的都是 false

#include<bits/stdc++.h>

#define maxn 100005 

using namespace std;

bool Mbg;

template<class T>
  
inline T read(){
	T r=0,f=0;
    char c;
	while(!isdigit(c=getchar()))f|=(c=='-');
	while(isdigit(c))r=(r*10)+(c^48),c=getchar();
	return f?-r:r;
}

int n,m,q;

int a[maxn];

struct QUERY{
	int opt,l,r;
}query[maxn];

int num;

namespace SGT{
	
#define lson cur<<1
#define rson cur<<1|1
	
	int tree[maxn<<2],tag[maxn<<2];
	
	inline void pushup(int cur){
		tree[cur]=tree[lson]+tree[rson];
	}

	void build(int cur,int lt,int rt){
		tag[cur]=-1;
		if(lt==rt){
			tree[cur]=(a[lt]>=num);
			return;
		}
		int mid=(lt+rt)>>1;
		build(lson,lt,mid);
		build(rson,mid+1,rt);
		pushup(cur);
	}

	inline void addtag(int cur,int lt,int rt,int val){
		tag[cur]=val;
		tree[cur]=(rt-lt+1)*val;
	}

	inline void pushdown(int cur,int lt,int rt){
		if(tag[cur]==-1)return;
		int mid=(lt+rt)>>1;
		addtag(lson,lt,mid,tag[cur]);
		addtag(rson,mid+1,rt,tag[cur]);
		tag[cur]=-1;
	}

	void update(int cur,int lt,int rt,int qx,int qy,int val){
		if(rt<qx||lt>qy)return;
		if(lt>=qx&&rt<=qy){
			addtag(cur,lt,rt,val);
			return;
		}
		pushdown(cur,lt,rt);
		int mid=(lt+rt)>>1;
		update(lson,lt,mid,qx,qy,val);
		update(rson,mid+1,rt,qx,qy,val);
		pushup(cur);
	}

	int ask(int cur,int lt,int rt,int qx,int qy){
		if(rt<qx||lt>qy)return 0;
		if(lt>=qx&&rt<=qy)return tree[cur];
		pushdown(cur,lt,rt);
		int mid=(lt+rt)>>1;
	    return ask(lson,lt,mid,qx,qy)+ask(rson,mid+1,rt,qx,qy);
	}
	
#undef lson
#undef rson
	
}

inline bool check(){
	SGT::build(1,1,n);
	for(int i=1;i<=m;i++){
		if(query[i].opt==0){
			int len=SGT::ask(1,1,n,query[i].l,query[i].r);
			SGT::update(1,1,n,query[i].r-len+1,query[i].r,1);
			SGT::update(1,1,n,query[i].l,query[i].r-len,0);
		}
		else{
			int len=SGT::ask(1,1,n,query[i].l,query[i].r);
			SGT::update(1,1,n,query[i].l+len,query[i].r,0);
			SGT::update(1,1,n,query[i].l,query[i].l+len-1,1);
		}
	}
	return SGT::ask(1,1,n,q,q);
}

bool Med;

int main(){
    double Mb=(&Mbg-&Med)/1e6;
	fprintf(stderr,"%.2lfMB\n",Mb=Mb<0?-Mb:Mb);
	if(Mb>256)fprintf(stderr,"MLE!!!\n");
	n=read<int>();
	m=read<int>();
	for(int i=1;i<=n;i++)
		a[i]=read<int>();
	for(int i=1;i<=m;i++){
		query[i].opt=read<int>();
		query[i].l=read<int>();
		query[i].r=read<int>();
	}
	q=read<int>();
	int lt=0,rt=n+1;
	while(lt+1<rt){
		int mid=(lt+rt)>>1;
		num=mid;
		if(check())lt=mid;
		else rt=mid;
	}
	printf("%d\n",lt);
	return 0;
}

标签:rt,cur,int,P2824,mid,lt,TJOI2016,HEOI2016,qx
From: https://www.cnblogs.com/blueparrot/p/17740484.html

相关文章

  • 题解 [HEOI2016/TJOI2016] 排序
    题目链接看到这道题按照套路首先想到二分答案(即二分\(q\)位置上的数,记作\(mid\))。再按照套路将大于\(mid\)的数字设为\(1\),将等于\(mid\)的数设为\(2\),小于\(mid\)的数字设为\(0\)。那么对于区间\([l,r,0]\)操作,应该先讲\(0,1,2\)的数量找出来,然后按照从小到大......
  • P2824 排序(二分答案加线段树)
    传送门很巧妙的一个题直接排序肯定会\(T\)飞我们发现问题只有一个:第\(q\)个位置上的数字不难想到从这里入手,二分答案,考虑第\(q\)个位置上的数字是什么,不妨设他为\(x\)然后把大于等于\(x\)的数变成\(1\),小于\(x\)的数变为\(0\),把他转换为一个\(01\)排序问题:对于区间\([l,r]\)......
  • P2824 排序(二分答案)
    题目简述给出一个$1$到$n$的排列,现在对这个排列序列进行$m$次局部排序,排序分为两种:0lr表示将区间$[l,r]$的数字升序排序1lr表示将区间$[l,r]$的数字降序排序这里是对下标在区间$[l,r]$内的数排序。最后询问第$q$位置上的数字。分析&性质申必题,对......
  • P4093[HEOI2016/TJOI2016]序列
    P4093[HEOI2016/TJOI2016]序列目录P4093[HEOI2016/TJOI2016]序列题目描述输入格式输出格式样例#1样例输入#1样例输出#1提示题目大意思路code题目描述佳媛姐姐过生日的时候,她的小伙伴从某宝上买了一个有趣的玩具送给他。玩具上有一个数列,数列中某些项的值可能会变化,但同一个......
  • P2824 [HEOI2016/TJOI2016]排序 题解
    题目传送门前言线段树好题!!!!咕咕了挺久的一道题目,很早之前就想写了,今天终于找了个时间A掉了。题意给定一个\(1\)到\(n\)的排列,有\(m\)次操作,分两种类型。1.0lr表示将下标在\([l,r]\)区间中的数升序排序。2.1lr表示将下标在\([l,r]\)区间中的数降序排序。给......
  • LibreOJ L2056 「TJOI / HEOI2016」序列
    https://loj.ac/p/2056CDQ优化DP模板?首先定义对于第\(x\)个数其可以变为的最小值为\(Min_x\),最大值为\(Max_x\),初始为\(M_x\)。因为最多只会变一次数,不难想到......
  • [HEOI2016/TJOI2016]排序
    https://www.luogu.com.cn/problem/P2824题解:仔细思考可以发现这道题与https://arc101.contest.atcoder.jp/tasks/arc101_b?lang=en是等价的。二分之后原问题就转化为了......
  • P2824 [HEOI2016/TJOI2016]排序
    P2824[HEOI2016/TJOI2016]排序题目大意这个难题是这样子的:给出一个\(1\)到\(n\)的排列,现在对这个排列序列进行\(m\)次局部排序,排序分为两种:0lr表示将区间\(......
  • 【HEOI2016_TJOI2016】排序(线段树分裂&合并)
    线段树分裂&合并入门题。对于每个单调段用一个权值线段树维护。一次操作相当于先对\(l,r\)所在的单调段的权值线段树分裂,然后再合并若干棵的权值线段树。线段树分裂和......
  • BZOJ 4551([Tjoi2016&Heoi2016]树-倒序并查集)
    Description在2016年,佳媛姐姐刚刚学习了树,非常开心。现在他想解决这样一个问题:给定一颗有根树(根为1),有以下两种操作:1.标记操作:对某个结点打上标记(在最开始,只有结点1有标记......