日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

题解【bzoj4653 [NOI2016] 区间】

發布時間:2024/4/17 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 题解【bzoj4653 [NOI2016] 区间】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

先按照長度排個序,然后依次添加區間。什么是添加?設這個區間是\([l,r]\),添加就是把\(a_l,a_{l+1},a_{l+2},{...},a_{r}\)都加上\(1\),其中\(a_i\)表示第\(i\)個位置被幾個區間覆蓋。拿走一個區間的含義就是把它們都減\(1\)。這個過程很顯然可以用線段樹維護。

如果在添加到一個區間 \(i\) 時,有一個點被區間覆蓋了\(M\)次,那么先更新答案,再把前面的加入過的區間一直拿直到沒有一個點被覆蓋\(M\)次。如何判斷有沒有點被覆蓋\(M\)次?因為是一個一個區間加的,所以只用維護一個\(a_i\)的最大值,看他是否\(=M\)就行了。

什么叫再把前面的加入過的區間一直拿直到沒有一個點被覆蓋\(M\)

比如你一直添加區間到第\(5\)個,此時有一個點被覆蓋了\(M\)次。這時你就將第一個區間拿出,如果此時依然有有一個點被覆蓋了\(M\)次,那么你就拿走第二個...

這個過程就好比一個隊列,可以從后面添加區間達到一個點被覆蓋了\(M\)次;從前面彈出區間直到沒有一個點被覆蓋了\(M\)次。

差不多就是這樣,還有注意一下\(l_i,r_i \leq 10^9\),開線段樹是要離散化的。上代碼:

#include <bits/stdc++.h> #define INF 1000000001 using namespace std; const int N = 500500; int n, m, cnt, tot, ans = INF; struct Seg {int l, r, len;bool operator < (const Seg &x) const {return len < x.len;} }a[N]; struct KEY {int d, id, se; }key[N * 2]; inline bool cmp1(KEY x, KEY y) {return x.d < y.d; } inline bool cmp2(KEY x, KEY y) {return x.id < y.id; } struct node {int left, right, Max, lazy;node *ch[2]; }pool[N * 4], *root; inline void pushup(node *r) {r->Max= max(r->ch[0]->Max, r->ch[1]->Max); } inline void pushdown(node *r) {if(!r->lazy) return ;r->Max += r->lazy;if(r->ch[0]) r->ch[0]->lazy += r->lazy;if(r->ch[1]) r->ch[1]->lazy += r->lazy;r->lazy = 0; return ; } inline void build(node *r, int left, int right) {r->left = left, r->right = right;if(left == right) return ;int mid = (left + right) >> 1;node *lson = &pool[++cnt], *rson = &pool[++cnt];r->ch[0] = lson, r->ch[1] = rson;build(lson, left, mid), build(rson, mid + 1, right); } inline void change(node *r, int left, int right, int d) {if(r->left == left && r->right == right) {r->lazy += d; return ;}pushdown(r);if(r->ch[0]->right >= right) change(r->ch[0], left, right, d);else if(r->ch[1]->left <= left) change(r->ch[1], left, right, d);else change(r->ch[0], left, r->ch[0]->right, d), change(r->ch[1], r->ch[1]->left, right, d);pushdown(r->ch[0]), pushdown(r->ch[1]), pushup(r); } int main() {scanf("%d%d", &n, &m);for(int i = 1; i <= n; i++) {scanf("%d%d", &a[i].l, &a[i].r);a[i].len = a[i].r - a[i].l;key[++tot].d = a[i].l, key[tot].id = tot;key[++tot].d = a[i].r, key[tot].id = tot;}sort(key + 1, key + tot + 1, cmp1);key[0].d = -1; key[0].se = 0;for(int i = 1; i <= tot; i++)if(key[i].d == key[i - 1].d) key[i].se = key[i - 1].se;else key[i].se = key[i - 1].se + 1;sort(key + 1, key + tot + 1, cmp2);for(int i = 1; i <= n; i++)a[i].l = key[i * 2 - 1].se, a[i].r = key[i * 2].se;sort(a + 1, a + n + 1);build(root = &pool[0], 1, 2 * n + 1);int pos = 1;change(root, a[1].l, a[1].r, 1);if(m == 1) ans = 0;for(int i = 2; i <= n; i++) {change(root, a[i].l, a[i].r, 1);while(root->Max >= m) {change(root, a[pos].l, a[pos].r, -1);ans = min(ans, a[i].len - a[pos].len);pos++;} }if(ans == INF) ans = -1;printf("%d\n", ans);return 0; }

轉載于:https://www.cnblogs.com/acfunction/p/10051289.html

總結

以上是生活随笔為你收集整理的题解【bzoj4653 [NOI2016] 区间】的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。