题解:洛谷 P11453([USACO24DEC] Deforestation S)
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;
}
}

浙公网安备 33010602011771号