NOI2016 區間 題解(線段樹 尺取法)

2022-03-26 10:28:01 字數 1516 閱讀 4522

題目鏈結

題目大意:給定$n$個區間$[l_i,r_i]$,選出$m$個區間使它們有乙個共同的位置$x$,且使它們產生的費用最小。求最小費用。費用定義為最長的區間長度減去最短區間長度。

因為區間順序改動又不影響答案,我們不妨按照長度排個序。看到資料範圍果斷離散化。

思考一種最樸素的做法:將排好序的區間逐一加入數軸,看有沒有乙個點被覆蓋的次數$\geq m$。

有的話就統計一下答案,然後將前面加入的數刪掉,直到$顯然用到了尺取法。維護是否有乙個點被覆蓋的次數可以用線段樹。

然後就可以成功a掉此題。

**:

#includeusing

namespace

std;

int n,m,maxx,b[1000005],cnt,size,head=0,tail=0,ans=0x3f3f3f3f

;struct

node

a[500005

];struct

tree

tree[

4000005

];inline

intread()

while(isdigit(ch))

return x*f;

}bool

cmp(node x,node y)

inline

void build(int index,int l,int

r)inline

void pushdown(int

index)

inline

void update(int index,int l,int r,int

x)

if(tree[index].lazy) pushdown(index);

int mid=(tree[index].l+tree[index].r)>>1

;

if (l<=mid) update(index*2

,l,r,x);

if (r>mid) update(index*2+1

,l,r,x);

tree[index].max=max(tree[index*2+1].max,tree[index*2

].max);

}int

main()

sort(b+1,b+cnt+1

); size=unique(b+1,b+cnt+1)-b-1

; sort(a+1,a+n+1

,cmp);

for (int i=1;i<=n;i++)

build(

1,1,maxx);

while(tailif (tree[1].maxbreak

;

while(head<=tail&&tree[1].max>=m)

}if (ans==0x3f3f3f3f) printf("-1"

);

else printf("%d"

,ans);

return0;

}

線段樹 NOI2016 區間

在數軸上有 n 個閉區間 l 1,r1 l 2,r2 l n,rn 現在要從中選出 m 個區間,使得這 m個區間共同包含至少乙個位置。換句話說,就是使得存在乙個 x 使得對於每乙個被選中的區間 l i,ri 都有 li x r i 對於乙個合法的選取方案,它的花費為被選中的最長區間長度減去被選中的最...

NOI2016 區間 線段樹

在數軸上有 n個閉區間 l1,r1 l2,r2 ln,rn 現在要從中選出 m 個區間,使得這 m個區間共同包含至少乙個位置。換句話說,就是使得存在乙個 x,使得對於每乙個被選中的區間 li,ri 都有 li x ri。對於乙個合法的選取方案,它的花費為被選中的最長區間長度減去被選中的最短區間長度。...

NOI2016 區間 線段樹

將區間按照長度排序,每次將相同長度的區間插入,直到有乙個點能被至少m個區間覆蓋,這個可以用線段樹維護。這時我們就可以刪除長度小的區間直到不滿足條件。重複做就可以了 1 include 2 include 3 include 4 include 5 include 6 define ll long l...