2500B站外题代码求调,玄一关
  • 板块灌水区
  • 楼主aike_6yoshi9
  • 当前回复0
  • 已保存回复0
  • 发布时间2024/10/29 19:14
  • 上次更新2024/10/29 19:21:05
查看原帖
2500B站外题代码求调,玄一关
1125690
aike_6yoshi9楼主2024/10/29 19:14

题面

实验室里有n种细胞,它们被排成了一行,从左往右编号1到n。我们可以用细胞分裂剂使一段区间的细胞分裂成两倍。
例如,对于这一行细胞 {1 2 3 3 4 5}, 我们在区间[2,5]使用分裂剂后就变成了 {1 2 2 3 3 3 3 4 4 5}.
在经过若干次操作后,请你找出指定区间中,哪种细胞的数量最多。  
第一行,两个整数n和m分别表示细胞的种数和操作的数量。 (1 <= n,m<= 50000)
解下来m行,每行描述一个操作。有两种操作:
Q l r,询问区间[l,r]的,数量最多的哪种细胞的个数
D l r, 使用分裂剂将区间[l,r]的细胞分裂成两倍


0 <= r – l <= 10^8, 1 <= l, r <= 细胞的数量

My code

#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e7+100;
int tree_sum[MAXN],tree_max[MAXN],tag[MAXN],a[MAXN];
int ls(int p){return p<<1;}
int rs(int p){return p<<1|1;}
void push_up(int p){
	tree_sum[p]=tree_sum[ls(p)]+tree_sum[rs(p)];
	tree_max[p]=max(tree_max[ls(p)],tree_max[rs(p)]);
}
void chan(int p,int pl,int pr){
	if(pl==pr){
		tree_max[p]=tree_max[p]=a[pl];
		return ;
	}
	int mid=(pl+pr)>>1;
	chan(ls(p),pl,mid);
	chan(rs(p),mid+1,pr);
	push_up(p);
}
void build(int p,int pl,int pr){
	if(pl==pr){
		tree_sum[p]=tree_max[p]=a[pl];
		return ;
	}
	tag[p]=0;
	int mid=(pl+pr)>>1;
	build(ls(p),pl,mid);
	build(rs(p),mid+1,pr);
	push_up(p);
}
void addtag(int p,int pl,int pr,int d){
	tag[p]+=d;
	tree_sum[p]=tree_sum[p]*pow(2,d);
	if(pl==pr) tree_max[p]=tree_sum[p];
}
void push_down(int p,int pl,int pr){
	if(tag[p]){
		int mid=(pl+pr)>>1;
		addtag(ls(p),pl,mid,tag[p]);
		addtag(rs(p),mid+1,pr,tag[p]);
		tag[p]=0;
	}
}
void update(int L,int R,int p,int pl,int pr){
	if(L<=pl&&pr<=R){
		addtag(p,pl,pr,1);
		return ;
	}
	push_down(p,pl,pr);
	int mid=(pl+pr)>>1;
	if(L<=mid) update(L,R,ls(p),pl,mid);
	if(R>mid) update(L,R,rs(p),mid+1,pr);
	push_up(p);
}
int find_k(int p,int pl,int pr,int k){
	if(pl==pr){
		return pl;
	}
	int mid=(pl+pr)>>1;
	if(tree_sum[ls(p)]>=k) return find_k(ls(p),pl,mid,k);
	else return find_k(rs(p),mid+1,pr,k-tree_sum[ls(p)]);
}
int query_sum(int L,int R,int p,int pl,int pr){
	if(L<=pl&&pr<=R){
		return tree_sum[p];
	}
	push_down(p,pl,pr);
	int mid=(pl+pr)>>1,res=0;
	if(L<=mid) res+=query_sum(L,R,ls(p),pl,mid);
	if(R>mid) res+=query_sum(L,R,rs(p),mid+1,pr);
	return res;
}
int query_max(int L,int R,int p,int pl,int pr){
	if(L<=pl&&pr<=R) return tree_max[p];
	int mid=(pl+pr)>>1,res;
	if(L<=mid) res=query_max(L,R,ls(p),pl,mid);
	if(R>mid) res=max(res,query_max(L,R,rs(p),mid+1,pr));
	return res;
}
int main(){
	int n,q;scanf("%d%d",&n,&q);
	for(int i=1;i<=n;i++) a[i]=1;
	build(1,1,n);
	while(q--){
		char op;cin>>op;
		int x,y;scanf("%d%d",&x,&y);
		if(op=='D'){
			int _left=find_k(1,1,n,x);
			int _right=find_k(1,1,n,y);
			if(_left+1<=_right-1) update(_left+1,_right-1,1,1,n);
			int leftsum;
			if(_left==1) leftsum=0;
			else leftsum=query_sum(1,_left-1,1,1,n);
			int rightsum;
			if(_right==1) rightsum=0;
			else rightsum=query_sum(1,_right-1,1,1,n);
			a[_left]+=a[_left]-(x-leftsum-1);
			if(_left!=_right) a[_right]+=y-rightsum;
			chan(1,1,n);
		}
		else{
			int _left=find_k(1,1,n,x);
			int _right=find_k(1,1,n,y);
			int ans=query_max(_left,_right,1,1,n);
			printf("%d\n",ans);
		}
	}
	return 0;
}
2024/10/29 19:14
加载中...