Educational Codeforces112 1555.E. Boring Segments(尺取+线段树)
Posted issue是fw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Educational Codeforces112 1555.E. Boring Segments(尺取+线段树)相关的知识,希望对你有一定的参考价值。
题意
给出 n n n条线段,若两个点在同一条线段内,那么可以在这两个点间移动
现在你需要选择一个线段的子集,代价是选择的最大权值线段和最小权值线段的差
最小化代价(保证一定存在解)
把线段 [ l , r ] [l,r] [l,r]的作用看成可以连通 ( l , l + 1 ) , ( l + 1 , l + 2 ) . . . ( r − 1 , r ) (l,l+1),(l+1,l+2)...(r-1,r) (l,l+1),(l+1,l+2)...(r−1,r)
那么从 1 1 1走到 m m m,意味着 i ∈ [ 1 , m − 1 ] i\\in[1,m-1] i∈[1,m−1]都连通了 ( i , i + 1 ) (i,i+1) (i,i+1)
这样我们就把线段右端点都减去 1 1 1,求一个子集能覆盖 [ 1 , m − 1 ] [1,m-1] [1,m−1]
要求最小化极差,我们可以用尺取的方法,先对线段的权值排序
然后尺取一段区间 [ L , R ] [L,R] [L,R],使得这 R − L + 1 R-L+1 R−L+1条线段刚好能覆盖 [ 1 , m − 1 ] [1,m-1] [1,m−1]
更新答案,然后移动区间.
于是问题变成如何动态维护当前尺取区间是否覆盖了 [ 1 , m − 1 ] [1,m-1] [1,m−1]
对于每次加入的线段 [ l i , r i ] [l_i,r_i] [li,ri],我们把这个区间内所有数加上 1 1 1
如果覆盖了 [ 1 , m − 1 ] [1,m-1] [1,m−1],那么每个点被覆盖的次数都大于 0 0 0,显然维护一个区间最小值即可
检查是否覆盖判一下 [ 1 , m − 1 ] [1,m-1] [1,m−1]的区间最小值即可
这样就可以用线段树维护,区间修改,区间最小值
总体复杂度 O ( n ∗ l o g ( m ) ) O(n*log(m)) O(n∗log(m))
#include <bits/stdc++.h>
using namespace std;
#define mid (l+r>>1)
#define ls (rt<<1)
#define rs (rt<<1|1)
#define lson ls,l,mid
#define rson rs,mid+1,r
const int maxn = 3e5+10;
const int N = 4e6+10;
int n,m;
struct p
{
int l,r,w;
bool operator < ( const p&tmp ) const
{
return w<tmp.w;
}
}a[maxn];
int laz[N],mi[N];
void pushdown(int rt,int l,int r)
{
if( laz[rt]==0 ) return;
mi[ls] += laz[rt], mi[rs] += laz[rt];
laz[ls] += laz[rt], laz[rs] += laz[rt];
laz[rt] = 0;
}
void add(int rt,int l,int r,int L,int R,int val)
{
if( l>R || r<L ) return;
if( l>=L && r<=R )
{
mi[rt] += val; laz[rt] += val;
return;
}
pushdown(rt,l,r);
add( lson,L,R,val ); add( rson,L,R,val );
mi[rt] = min( mi[ls],mi[rs] );
}
int solve()
{
int r = 1, res = 1e6;
for(int l=1;l<=n;l++)
{
while( mi[1]<=0 && r<=n )
add(1,1,m,a[r].l,a[r].r,1 ),r++;
if( mi[1]>0 ) res = min( res,a[r-1].w-a[l].w );
add( 1,1,m,a[l].l,a[l].r,-1 );
}
return res;
}
signed main()
{
scanf("%d%d",&n,&m ); m--;
for(int i=1;i<=n;i++)
{
scanf("%d%d%d",&a[i].l,&a[i].r,&a[i].w );
a[i].r--;
}
sort( a+1,a+1+n );
cout << solve();
}
以上是关于Educational Codeforces112 1555.E. Boring Segments(尺取+线段树)的主要内容,如果未能解决你的问题,请参考以下文章
Educational Codeforces Round 112 (Rated for Div. 2)-A. PizzaForces-题解
Educational Codeforces Round 112 (Rated for Div. 2)-C. Coin Rows-题解
Educational Codeforces Round 112 (Rated for Div. 2)-C. Coin Rows-题解
Educational Codeforces Round 112 (Rated for Div. 2)-B. Two Tables-题解
Educational Codeforces Round 112 (Rated for Div. 2)-B. Two Tables-题解
Educational Codeforces Round 112 (Rated for Div. 2) B. Two Tables