1. 程式人生 > >[NOI 2016] 區間

[NOI 2016] 區間

read ons spa uil bre bit ret www .com

[題目鏈接]

https://www.lydsy.com/JudgeOnline/problem.php?id=4653

[算法]

首先將區間按長度排序

那麽 , 滿足條件的一定是一段連續的區間 , [Li , Ri] , [Li+1,Ri+1] ... [Lj , Rj]

我們不妨枚舉每一個L , 不難發現當L遞增時 , 滿足條件的 , 最小的R同樣是單調遞增的 , 不妨用Two-Pointers計算這個最小的R並更新答案

我們還需用線段樹維護當前被覆蓋最多次的位置被覆蓋了多少次

由於每個位置都會被訪問並更新一次 , 故時間復雜度為 : O(NlogN)

[代碼]

#include<bits/stdc++.h>
using namespace std;
#define MAXN 500010
#define MAXM 200010
const int inf = 2e9;

struct range
{
        int l , r;
} a[MAXN];

int n , m , len;
int tmp[MAXN << 1] , l[MAXN] , r[MAXN];

struct Segment_Tree
{
        struct Node
        {
                int
l , r; int mx , tag; } Tree[MAXN << 4]; inline void build(int index , int l , int r) { Tree[index].l = l; Tree[index].r = r; Tree[index].mx = Tree[index].tag = 0; if (l == r) return;
int mid = (l + r) >> 1; build(index << 1 , l , mid); build(index << 1 | 1 , mid + 1 , r); } inline void pushdown(int index) { Tree[index << 1].mx += Tree[index].tag; Tree[index << 1 | 1].mx += Tree[index].tag; Tree[index << 1].tag += Tree[index].tag; Tree[index << 1 | 1].tag += Tree[index].tag; Tree[index].tag = 0; } inline void update(int index) { Tree[index].mx = max(Tree[index << 1].mx , Tree[index << 1 | 1].mx); } inline void modify(int index , int l ,int r , int value) { if (Tree[index].l == l && Tree[index].r == r) { Tree[index].mx += value; Tree[index].tag += value; return; } pushdown(index); int mid = (Tree[index].l + Tree[index].r) >> 1; if (mid >= r) modify(index << 1 , l , r , value); else if (mid + 1 <= l) modify(index << 1 | 1 , l , r , value); else { modify(index << 1 , l , mid , value); modify(index << 1 | 1 , mid + 1 , r , value); } update(index); } inline int query() { return Tree[1].mx; } } SGT; template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); } template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); } template <typename T> inline void read(T &x) { T f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == -) f = -f; for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - 0; x *= f; } inline bool cmp(range a , range b) { return a.r - a.l < b.r - b.l; } int main() { read(n); read(m); for (int i = 1; i <= n; i++) { read(a[i].l); read(a[i].r); tmp[i * 2 - 1] = a[i].l; tmp[i * 2] = a[i].r; } sort(tmp + 1 , tmp + 2 * n + 1); len = unique(tmp + 1 , tmp + 2 * n + 1) - tmp - 1; sort(a + 1 , a + n + 1 , cmp); for (int i = 1; i <= n; i++) { l[i] = lower_bound(tmp + 1 , tmp + len + 1 , a[i].l) - tmp; r[i] = lower_bound(tmp + 1 , tmp + len + 1 , a[i].r) - tmp; } SGT.build(1 , 1 , len); int ans = inf , rgt = 0; for (int i = 1; i <= n; i++) { bool flg = false; while (rgt <= n) { if (SGT.query() >= m) { flg = true; break; } ++rgt; if (rgt > n) break; SGT.modify(1 , l[rgt] , r[rgt] , 1); } if (flg) chkmin(ans , (tmp[r[rgt]] - tmp[l[rgt]]) - (tmp[r[i]] - tmp[l[i]])); else break; SGT.modify(1 , l[i] , r[i] , -1); } printf("%d\n" , ans != inf ? ans : -1); return 0; }

[NOI 2016] 區間