题解:洛谷 P11453([USACO24DEC] Deforestation S)

Link

1. Description

\(n\) 棵树和 \(k\) 个限制,限制形如 \((l,r,t)\),表示 \([l,r]\) 这个区间内至少要有 \(t\) 棵树,问最多可以砍掉多少棵树后仍然保证满足所有限制。

2. Solution

简单的贪心。

首先,这个问题可以转换为:有 \(n\) 棵可以种的树,在满足限制的前提下,最少要种的几棵树。

我们不妨将所有限制区间按右端点升序排序,当我们需要种树的时候,显然种还没有种的坐标小于等于 \(r\) 的最大的树,这样贡献最多。

然后我们还需要维护一个区间内已经种了多少棵树,可以使用树状数组或线段树维护单点加和区间和。

那么这道题就写完了。

3. Code

/*by qwer6*/
/*略去缺省源和快读快写*/
const int N=1e5+5;
int n,k,ans,tot;
int x[N],tmp[N*3];
priority_queue<int>q;
struct Query{
	int l,r,t;
	bool operator <(const Query &a)const{
		return r<a.r;
	}
}b[N]; 
struct Binary_tree{
	int n;
	int c[N*3];
	#define lowbit(x) (x&-x)
	void init(int _n=0){
		n=_n;
		for(int i=1;i<=n;i++)c[i]=0;
	}
	void add(int x,int v){
		for(int i=x;i<=n;i+=lowbit(i))c[i]+=v;
	}
	int query(int x){
		int res=0;
		for(int i=x;i;i-=lowbit(i))res+=c[i];
		return res;
	}
	int query(int l,int r){
		return query(r)-query(l-1);
	}
	#undef lowbit
}bit;
signed main(){
	int t;
	read(t);
	while(t--){
		tot=0;
		read(n),read(k);
		for(int i=1;i<=n;i++)tmp[++tot]=read(x[i]);
		for(int i=1;i<=k;i++){
			read(b[i].l),read(b[i].r),read(b[i].t);
			tmp[++tot]=b[i].l,tmp[++tot]=b[i].r;
		}
		sort(tmp+1,tmp+tot+1);
		tot=unique(tmp+1,tmp+tot+1)-tmp-1;
		for(int i=1;i<=n;i++)x[i]=lower_bound(tmp+1,tmp+tot+1,x[i])-tmp;
		for(int i=1;i<=k;i++){
			b[i].l=lower_bound(tmp+1,tmp+tot+1,b[i].l)-tmp;
			b[i].r=lower_bound(tmp+1,tmp+tot+1,b[i].r)-tmp;
		}
		sort(x+1,x+n+1);
		sort(b+1,b+k+1);
		bit.init(tot);
		while(!q.empty())q.pop();
		ans=n;
		for(int i=1,j=1;i<=k;i++){
			while(j<=n&&x[j]<=b[i].r){
				q.push(x[j]);
				j++;
			}
			while(bit.query(b[i].l,b[i].r)<b[i].t){
				ans--;
				bit.add(q.top(),1);
				q.pop();
			}
		}
		write(ans),Nxt;
	}
}
posted @ 2025-05-04 10:01  陈牧九  阅读(38)  评论(0)    收藏  举报