链接:https://codeforces.com/contest/1555/problem/E
题意:
在数轴上给3e5条从l到r权为w的线,要求选择其中一些线,将1 ~ m完全覆盖。
要求输出选择方案中 max与min权值 之差 最小的结果。
题解:
用线段树维护覆盖的区间
设置尺取选中范围l与r
按w从小到大排序,依次将区间加入线段树,也就是r不断右移
如果出现符合条件的情况,就记录当前的大小差值
并且将l持续右移,同时将区间从线段树中移除,直至不符合为止
取大小差值的min即可
过程有点像扫描线(个人感觉)
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
int t[maxn*4];
int b[maxn*4];
void pushup(int rt){
t[rt]=min(t[rt<<1],t[rt<<1|1]);
}
void update(int L,int R,int l,int r,int rt,int val){
if(L<=l&&r<=R){
t[rt]+=val;
b[rt]+=val;
return;
}
int mid=(l+r)>>1;
if(b[rt]&&l!=r){
b[rt<<1]+=b[rt];
b[rt<<1|1]+=b[rt];
t[rt<<1]+=b[rt];
t[rt<<1|1]+=b[rt];
b[rt]=0;
}
if(mid>=L){
update(L,R,l,mid,rt<<1,val);
}
if(mid<R){
update(L,R,mid+1,r,rt<<1|1,val);
}
pushup(rt);
}
int query(int L,int R,int l,int r,int rt){
if(L<=l&&r<=R){
return t[rt];
}
int mid=(l+r)>>1;
int ans=1e6;
if(b[rt]&&l!=r){
b[rt<<1]+=b[rt];
b[rt<<1|1]+=b[rt];
t[rt<<1]+=b[rt];
t[rt<<1|1]+=b[rt];
b[rt]=0;
}
if(mid>=L){
ans=min(query(L,R,l,mid,rt<<1),ans);
}
if(mid<R){
ans=min(query(L,R,mid+1,r,rt<<1|1),ans);
}
return ans;
}
struct line{
int l,r,w;
bool operator <(const line &a)const{
return w<a.w;
}
}li[300040];
int main(){
ios::sync_with_stdio(0);
int n,m;
cin>>n>>m;
for(int i=0;i<n;i++){
cin>>li[i].l>>li[i].r>>li[i].w;
}
sort(li,li+n);
int ans=1e8;
queue <line> q;
for(int i=0;i<n;i++){
int w=li[i].w;
update(li[i].l,li[i].r-1,1,m,1,1);
q.push(li[i]);
while(query(1,m-1,1,m,1)>0){
line t=q.front();
ans=min(ans,w-t.w);
update(t.l,t.r-1,1,m,1,-1);
q.pop();
}
}
cout<<ans<<endl;
//system("pause");
return 0;
}