提供一种O(h log h)的奇葩思路(题解中没有提到的)
查看原帖
提供一种O(h log h)的奇葩思路(题解中没有提到的)
363605
Accelerator07楼主2021/11/30 17:16

可以考虑维护一个数组chao(超),chao[i]表示高度超过i的有几块砖。后强行模拟删砖的步骤即可。又因为其中由于涉及到了区间加减,可考虑用线段树进行维护。

附AC Code:

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+5;
int n,a[N],maxx=-0x3f3f3f3f,minn=0x3f3f3f3f,k,chao[N],biaoji[N],c[N];
struct SegmentTree{
	int l,r;
	int add,data;
	#define l(x) tree[x].l
	#define r(x) tree[x].r
	#define add(x) tree[x].add
	#define data(x) tree[x].data
}tree[N*4];
inline void build(int p,int l,int r){
	l(p)=l,r(p)=r;
	if(l==r){
		data(p)=chao[l];
		return;
	}
	int mid=l+r>>1;
	build(p<<1,l,mid);
	build(p<<1|1,mid+1,r);
	data(p)=data(p<<1)+data(p<<1|1);
}
inline void spread(int x){
	if(add(x)){
		data(x<<1)+=add(x)*(r(x<<1)-l(x<<1)+1);
		data(x<<1|1)+=add(x)*(r(x<<1|1)-l(x<<1|1)+1);
		add(x<<1)+=add(x);
		add(x<<1|1)+=add(x);
		add(x)=0;
	}
}
inline void change(int p,int l,int r,int d){
	if(l(p)>=l && r(p)<=r){
		data(p)+=d*(r(p)-l(p)+1);
		add(p)+=d;
		return;
	}
	spread(p);
	int mid=l(p)+r(p)>>1;
	if(l<=mid) change(p<<1,l,r,d);
	if(r>mid) change(p<<1|1,l,r,d);
	data(p)=data(p<<1)+data(p<<1|1);
}
inline int query(int p,int l,int r){
	if(l(p)>=l&&r(p)<=r) return data(p);
	spread(p);
	int mid=l(p)+r(p)>>1,val=0;
	if(l<=mid) val+=query(p<<1,l,r);
	if(r> mid) val+=query(p<<1|1,l,r);
	return val;
}
signed main(){
	cin>>n>>k;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		maxx=max(maxx,a[i]),minn=min(minn,a[i]);
	}
	sort(a+1,a+n+1);
	int ans=0;
	if(a[1]==a[n]){
		puts("0");
		return 0;
	} 
	for(int i=1;i<=n;i++) biaoji[a[i]]++;
	int lst=-1,tmp=-1,cnt=0;
	for(int i=maxx;i>=0;i--){
		if(biaoji[i]){
			if(lst!=-1) chao[i]=chao[lst]+(lst-i)*cnt;
			tmp=biaoji[i];
			lst=i;
			cnt+=biaoji[i];
		}
		else chao[i]=chao[lst]+(lst-i)*cnt;
	}
	build(1,0,maxx);
	bool flag=true;
	for(int i=maxx;i>=minn;i--){
		if(query(1,i,i)<=k && query(1,i-1,i-1)>k){
			ans++;
			flag=false;
			change(1,0,i,-1*query(1,i,i));
		}
		else flag=true;
	}
	cout<<ans+flag<<endl;
	return 0;
}
2021/11/30 17:16
加载中...