蓝桥杯2021真题-双向排序(线段树)

蓝桥杯2021真题-双向排序(线段树)_第1张图片

 升序区标记为1,降序区标记为0,用线段树进行区间维护,AC代码如下:

//2021省赛I题-双向排序(线段树) 
#include 
#include 
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define _for(i,a,b) for(int i=(a);i<(b);i++)
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 100000+5;
vector ans[2];
struct node{
	int l,r;    //该区间的左右端点 
	int sum;    //该区间中1的个数 
	int lazy;   //把该区间的值全部赋为lazy(0 or 1) 
};
node node[maxn*4];

void push_up(int num){          //向上更新函数
	node[num].sum=node[num<<1].sum+node[num<<1|1].sum;
}
void push_down(int num){      //下推懒惰标记 
	if(node[num].lazy==-1){
		return;
	}
	int lazy=node[num].lazy;
	node[num<<1].lazy=lazy;
	node[num<<1].sum=(node[num<<1].r-node[num<<1].l+1)*lazy;
	node[num<<1|1].lazy=lazy;
	node[num<<1|1].sum=(node[num<<1|1].r-node[num<<1|1].l+1)*lazy;
	node[num].lazy=-1;
}       
void build(int l,int r,int num){  //初始化线段树 
    node[num].l=l;
    node[num].r=r;
    node[num].lazy=-1;
	if(l==r){
		node[num].sum=1;
		return;
	}
	int mid=(l+r)>>1;
	build(l,mid,num<<1);
	build(mid+1,r,num<<1|1);
	push_up(num);
	
}
void update0(int cnt,int num){
	int cnt_1=node[num].sum;
	if(cnt_1<=cnt){
		node[num].sum=0;
		node[num].lazy=0;
		return;
	}
	push_down(num);
	int cnt_l_1=node[num<<1].sum;
	int cnt_r_1=node[num<<1|1].sum;
	if(cnt_l_1>=cnt){
		update0(cnt,num<<1);
	}
	else{
		update0(cnt_l_1,num<<1);
		update0(cnt-cnt_l_1,num<<1|1);
	}
	push_up(num);  //不能忘了这一步,还要向上更新 
}
void update1(int cnt,int num){
	int cnt_0=(node[num].r-node[num].l+1)-node[num].sum;
	if(cnt_0<=cnt){
		node[num].sum=(node[num].r-node[num].l+1)*1;
		node[num].lazy=1;
		return;
	}
	push_down(num);
	int cnt_l_0=(node[num<<1].r-node[num<<1].l+1)-node[num<<1].sum;
	int cnt_r_0=(node[num<<1|1].r-node[num<<1|1].l+1)-node[num<<1|1].sum;
	if(cnt_l_0>=cnt){
		update1(cnt,num<<1);
	}
	else{
		update1(cnt_l_0,num<<1);
		update1(cnt-cnt_l_0,num<<1|1);
	}
	push_up(num);
}
int query(int pos,int num){
	if(node[num].l==node[num].r){
		return node[num].sum;
	}
	push_down(num);
	int mid=(node[num].r+node[num].l)>>1;
	if(pos<=mid){
		return query(pos,num<<1);
	}
	else{
		return query(pos,num<<1|1);
	}
}

int main(){
	int n,m;
	cin>>n>>m;
	build(1,n,1);
	int pre_q=1;
	while(m--){
		int p,q;
		cin>>p>>q;
		if(p){
			if(pre_q<=q) continue;
			else{
				update1(pre_q-q,1);  //规定分解点pre_q始终在升序区(1) 
				pre_q = q;
			}
		}
		else{
			if(q=0;i--){
		cout<

蓝桥杯2021真题-双向排序(线段树)_第2张图片

 

你可能感兴趣的:(蓝桥杯,职场和发展)