题解——A君的问题(a)(值域线段树)

题解——A君的问题(a)

这道题很水,但不要问ssw02为什么要在这时做一道B层的题
因为ssw02再换板子,而这道题就是二分值域线段树的裸题
感谢神犇SXK提供优质的模板参考


题目搬运

【题目描述】

A君来到了一个蛋糕店,蛋糕店有n个位置顺次摆放着若干蛋糕,从左到右位置编号依次递增。当有客人来的时候服务生会把有些位置的蛋糕打包给客人,也可能会在某个没有蛋糕的空位放上一个蛋糕。A君想知道在某一时刻从左数第k个蛋糕的位置。

【输入数据】

第一行一个正整数n,m,其中n表示位置数量,m表示客人的数量。第二行n个数为0或1,第i个数表示开始时没有蛋糕(0)或者有蛋糕(1)。接下来共m行每行俩个数p,k,其中k如上文,p表示第p个位置有无蛋糕的情况发生了变化。

【输出数据】

m行,每行一个数表示询问的结果,若不存在k个蛋糕则输出”-1”(不含引号)。

解题思路

没有思路,单点修改+单点查询(查询二分当前区间个数就可以了)

我只是想把它当个板子记一下而已(以前的太丑了)

AC code

#include<bits/stdc++.h>
using namespace std; 
const  int  MAXN = 500005 ;
int N , M , num , sum[ MAXN<<2 ] , a[ MAXN ] ;
inline int read(){
	int s=0 ; char g=getchar() ;while(g>'9'||g<'0')g=getchar() ;
	while(g>='0'&&g<='9')s=s*10+g-'0',g=getchar();return s ;
}
void build( int p , int l , int r ){
	if( l == r ){
		sum[ p ] = a[ l ] ; return ;
	}
	int  mid = (l+r)>>1 ; 
	build( p<<1 , l , mid ) ;
	build( p<<1|1 , mid+1 , r ) ;
	sum[ p ] = sum[ p<<1 ] + sum[ p<<1 | 1 ] ;
}
void  change_a( int p , int  l , int r , int x , int v ){//和普通线段树没有区别
	sum[ p ] += v ;
	if( l==r )return ;
	int  mid = (l+r)>>1 ;
	if( x <= mid )change_a( p<<1 , l , mid , x , v ) ;
	else change_a( p<<1|1 , mid+1 , r , x , v ) ;
	sum[ p ] = sum[ p<<1 ]+sum[ p<<1|1 ] ;
}
int  ask( int p , int l , int r , int k ){
	if( l == r )return l ;
	int  mid = (l+r)>>1 ;//二分个数,判断位置
	if( sum[ p<<1 ] >= k )return ask( p<<1 , l , mid , k );
	else return ask( p<<1|1 , mid+1 , r , k-sum[p<<1] );
}
int main(){
	N = read() , M = read() ;
	for( register int i = 1 ; i <= N ; ++i )
	a[ i ] = read() , num += a[ i ] ; 
	build( 1 , 1 , N ) ; 
	while( M-- ){
		int  m1 = read() , m2 = read() ;
		if( a[ m1 ] )
		    change_a( 1 , 1 , N , m1 , -1 ),a[m1]=0,num-- ;
		else change_a( 1 , 1 , N , m1 , 1 ),a[m1]=1,num++ ;
		if( m2 > num )printf("-1
") ;
		else printf("%d
",ask( 1 , 1 , N , m2 ) ) ;
	}
	return 0 ;
}

它就是个板子,ssw02还要改动态区间第K大,先溜了。(本博客无任何价值)

原文地址:https://www.cnblogs.com/ssw02/p/11240582.html