首页 > 其他分享 >洛谷 P2824 [HEOI2016/TJOI2016] 排序(二分,线段树)

洛谷 P2824 [HEOI2016/TJOI2016] 排序(二分,线段树)

时间:2024-05-12 16:41:37浏览次数:27  
标签:二分 排序 洛谷 int P2824 mid TJOI2016 include id

传送门

解题思路

据说是经典思路:把多次排序转化成二分+01序列。
首先二分所求位置的数字是啥,将大于mid的数字变成1,将小于等于mid的数字变成0。
这样在排序的时候就相当于统计区间里的1的个数(区间和),然后区间全部变成0或者1。
也就是区间修改,区间求和,线段树可以实现。

AC代码

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<iomanip>
#include<ctime>
#include<stack>
using namespace std;
inline int read(){
	int x=0,f=1;char c=getchar();
	while(!(c>='0'&&c<='9')) {if(c=='-') f=-1;c=getchar();}
	while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
	return x*f;
}
const int maxn=1e5+5;
struct node{
	int op,l,r;
}b[maxn];
int d[maxn*4],lazy[maxn*4],a0[maxn],a[maxn];
inline void pushup(int id){
	d[id]=d[id*2]+d[id*2+1];
}
inline void pushdown(int id,int l,int r){
	if(lazy[id]==-1) return;
	lazy[id*2]=lazy[id*2+1]=lazy[id];
	int mid=(l+r)/2;
	d[id*2]=lazy[id]*(mid-l+1);
	d[id*2+1]=lazy[id]*(r-mid);
	lazy[id]=-1;
}
void add(int id,int l,int r,int x,int y,int v){
	if(x>y) return;
	if(x<=l&&r<=y){
		lazy[id]=v;
		d[id]=v*(r-l+1);
		return;
	}
	pushdown(id,l,r);
	int mid=(l+r)/2;
	if(x<=mid) add(id*2,l,mid,x,y,v);
	if(y>mid) add(id*2+1,mid+1,r,x,y,v);
	pushup(id); 
}
int query(int id,int l,int r,int x,int y){
	if(x<=l&&r<=y) return d[id];
	pushdown(id,l,r);
	int mid=(l+r)/2;
	int res=0;
	if(x<=mid) res+=query(id*2,l,mid,x,y);
	if(y>mid) res+=query(id*2+1,mid+1,r,x,y);
	return res;
}
int main()
{
    //ios::sync_with_stdio(false);
	int n=read(),m=read();
	for(int i=1;i<=n;i++) a0[i]=read(); 
	for(int i=1;i<=m;i++){
		b[i].op=read();
		b[i].l=read();
		b[i].r=read();
	}
	int q=read();
	int l=1,r=n;
	while(l<r){
		memset(d,0,sizeof(d));
		memset(lazy,-1,sizeof(lazy));
		int mid=(l+r)/2;
		for(int i=1;i<=n;i++) add(1,1,n,i,i,(a0[i]>mid));
		for(int i=1;i<=m;i++){
			int num=query(1,1,n,b[i].l,b[i].r);
			if(b[i].op==1){
				add(1,1,n,b[i].l,b[i].l+num-1,1);
				add(1,1,n,b[i].l+num,b[i].r,0);
			}else{
				add(1,1,n,b[i].r-num+1,b[i].r,1);
				add(1,1,n,b[i].l,b[i].r-num,0);
			}
		}
		if(query(1,1,n,q,q)){
			l=mid+1;
		}else{
			r=mid;
		}
	}
	cout<<l<<endl;
    return 0;
}

标签:二分,排序,洛谷,int,P2824,mid,TJOI2016,include,id
From: https://www.cnblogs.com/yinyuqin/p/18187922

相关文章

  • 洛谷题单指南-动态规划3-Zuma
    原题链接:https://www.luogu.com.cn/problem/CF607B题意解读:从一组整数中取连续的回文子串,求最少几次可以取完。解题思路:状态表示:设dp[i][j]表示取i~j之间的回文子串所需的最少次数,a[i]表示第i个数状态转移:如果a[i]==a[j],dp[i][j]=dp[i+1][j-1],因为首尾如果相等,其必然可以......
  • 5.10洛谷收获
    1.求幂函数#includepow(a,b);计算a的b次幂2.error:invalidtypes'int[int]'forarraysubscript|记住这个错误吧,犯过好多次了数组变量名不一致或者是没定义数组空间不够变量名和数组名重复定义3.快速幂快速幂本质上是一个倍增问题,比如说要求6的34次方如果34个6相乘......
  • #Trie#洛谷 6018 [Ynoi2010] Fusion tree
    题目给定一棵树,树上每个节点都有点权,需要实现三种操作,第一种是将与\(x\)相邻的所有节点点权加一,第二种是单点减小点权,第三种是查询与\(x\)相邻的所有节点点权的异或和分析相邻实际上就是父节点和子节点,不妨将其拆开考虑,需要解决单点查询单点修改的问题,考虑维护\(n\)......
  • 洛谷题单指南-动态规划3-P1775 石子合并(弱化版)
    原题链接:https://www.luogu.com.cn/problem/P1775题意解读:计算合并石子的最小代价,区间DP。解题思路:状态表示:dp[i][j]表示将第i~j堆石子合并的最小代价,m[i]表示第i堆石子质量,s[i]表示前i堆石子质量前缀和状态转移:考虑最后一次合并,设最后一次合并是将i~k合成的一堆与k+1~j合成......
  • 洛谷题单指南-动态规划2-P3147 [USACO16OPEN] 262144 P
    原题链接:https://www.luogu.com.cn/problem/P3147题意解读:将一组数据两两相邻且相同的合并,合并成一个数值+1的数,求合并后的最大值。解题思路:考虑合并后的最大数i,其最后一次必然是由两个i-1合并而来的设dp[i][j]表示以j为左端点,合并最大值为i时的右端点的下一个位置如图:dp[i......
  • 5.9洛谷收获
    今天发现了一个有用的容器,那就是向量,用bool类型的向量简直不要太方便,尤其是对于二极管问题,比如B2094然后用向量模拟栈也比较方便点击查看代码#include<iostream>#include<vector>usingnamespacestd;classStack{private:vector<int>elements;public://......
  • 洛谷 P1031 [NOIP2002 提高组] 均分纸牌 题解
    题目简述有$N$堆纸牌,编号分别为$1,2,\ldots,N$。每堆上有若干张,但纸牌总数必为$N$的倍数。可以在任一堆上取若干张纸牌,然后移动。移牌规则为:在编号为$1$堆上取的纸牌,只能移到编号为$2$的堆上;在编号为$N$的堆上取的纸牌,只能移到编号为$N-1$的堆上;其他堆上取的纸牌,可......
  • 洛谷 P1012 [NOIP1998 提高组] 拼数 题解
    题目简述设有$n$个正整数$a_1\dotsa_n$,将它们联接成一排,相邻数字首尾相接,组成一个最大的整数。题目分析定义设$X$为数字$x$的字符串形式。$A+B$表示字符串$A$和字符串$B$相连组成的字符串。思路既然要构造最优解,显然如果有不优的情况的话,就需要对序列进行......
  • #dp,Dilworth定理#洛谷 4934 礼物
    题目传送门分析首先,可以放在一起当且仅当\(\max\{a_i,a_j\}\&\min\{a_i,a_j\}\neq\min\{a_i,a_j\}\)根据Dilworth定理可知最小链划分中链的数目等于最长反链的长度所以设\(dp[i]\)表示以\(i\)为结尾的反链的最大长度,则\(dp[i]=\max_{j|i}\{dp[j]\}+[a_k==i]\)......
  • 洛谷题单指南-动态规划2-P4310 绝世好题
    原题链接:https://www.luogu.com.cn/problem/P4310题意解读:求最长的子序列长度,使得每相邻两个元素&操作不为0。解题思路:直观来看,可以通过类似最长上升子序列的算法,进行状态转移,但是复杂度为O(n^2),会超时状态表示:dp[i]表示前i个数能产生满足条件的子序列的最长长度状态转移:dp......