題解 NOI2016區間

2022-02-27 11:43:29 字數 1483 閱讀 8741

two - pointer 第一題…… 大概就是對於一段連續的區間求解,使用兩個指標不斷卡區間的長度直到區間不滿足條件吧。

這題只要對區間以長度從小到大排一下序,然後使用兩個指標指向區間。線段樹維護被覆蓋最多次數的節點被覆蓋了多少次。如果滿足條件,由於我們是在第一次判斷的時候發現它滿足條件的,所以最後加入的這個區間一定對於答案產生了貢獻,也就是最大的區間。要使最小區間最大化,我們只需讓前面的指標慢慢往後跳直到不符合條件即可。

#include using

namespace

std;

#define maxn 5000000

#define inf 999999999

intn, m, tot, cnt, b[maxn];

int ans =inf, num[maxn];

intmark[maxn];

map

map;

intread()

while(c >= '

0' && c <= '

9') x = x * 10 + c - '

0', c =getchar();

return x *k;

}struct

node

}a[maxn];

void push_down(int

p)void update(int p, int l, int r, int l, int r, int

x)

if(l > r || r < l) return

; push_down(p);

int mid = (l + r) >> 1

; update(p

<< 1, l, mid, l, r, x), update(p << 1 | 1, mid + 1

, r, l, r, x);

num[p] = max(num[p << 1], num[p << 1 | 1

]);}

intmain()

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

sort(b + 1, b + 1 + tot); b[0] = -1

;

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

if(b[i] != b[i - 1]) map[b[i]] = ++cnt;

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

for(int i = 1; i <= n; i ++) a[i].l = map[a[i].l], a[i].r =map[a[i].r];

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

ans = min(ans, tem -tem2);

}if(ans == inf) printf("

-1\n");

else printf("

%d\n

", ans);

return0;

}

NOI2016 區間 題解

題目大意 有n個區間,當有m個區間有公共部分時,求m個區間長度的最大值與最小值之差的最小值。思路 按區間的長度從小到大排序,可知連續的幾個區間最優,則用兩個指標指其頭尾,線性掃瞄,再用線段樹區間覆蓋。1 include2 include3 include4 define n 1000009 5 de...

線段樹 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。對於乙個合法的選取方案,它的花費為被選中的最長區間長度減去被選中的最短區間長度。...