區間(貪心做法 線段樹優化)

2022-05-09 15:46:57 字數 2241 閱讀 4302

題目

這道題目的話,按\(r\)從小到大排序,然後如果對於當前的區間沒有滿足至少\(c_i\)個的話,就盡量選右邊的沒有選過的數字。顯而易見是正確的

正確性證明:

對於當前這個區間\(i\)而言,如果前面\(i-1\)個區間已經是用了最少的數字,且盡量的把數字湊到\(i\)區間的\(l\)的的話,如果想要讓前\(i-1\)的區間對\(i\)區間的貢獻\(+1\),那麼前\(i-1\)個區間必須多用乙個數字。

那麼我們證明,全部放右邊能讓前\(i\)個區間也滿足這樣的性質。(其實就是數學歸納法)

首先證明最少,首先前面是已經盡量的靠右邊放了,也就是說對於這個區間的貢獻是已經最大化了,那麼由於其是最小了,所以我們不能讓其更小,那麼我們就只能求讓其貢獻變大來減少我們在這個區間放的數字個數,但是由於貢獻增加數和區間少放的數字呈\(1:1\)關係,所以並不會讓總數字減少。

那麼我們繼續證明貢獻是最大化的情況,由於按\(r\)排序,所以對於第\(i+1\)區間交集部分而言,假設交集部分是\([x,r]\),如果這個區間的數字都被選了,那麼就是最大化的情況,如果沒有放滿,說明我們可以多放乙個數字增加貢獻,但是這樣就違背了數字總個數最小的法則,而且前\(i-1\)個區間也是最小的,並不能給第\(i\)個區間提供乙個放數字的可能,所以我們並不能增加貢獻,同時如果要增加乙個貢獻,那麼也要讓總數字加\(1\)。

當然,有可能第\(i+1\)個區間還和第\(y\)個區間有交集,然後讓前\(y\)個區間總個數\(+1\),然後貢獻\(+1\),重點是由於\(r\)從小到大排,所以這個貢獻是有可能作用於第\(i\)個區間的,這樣不就讓貢獻減一的同時讓個數\(+1\)了嗎?但是由於這個第\(i\)個區間接收到了貢獻,少放了乙個數字,且這個數字的位置一定大於等於,第\(y\)個區間增加貢獻所放的數字位置,這樣這個少放的數字也會作用於第\(i+1\)個區間,所以其實是沒有增加貢獻的,且由於數字前移了,對於後面的區間所能做的貢獻可能會減少,是極其不優秀的。

所以第\(i\)個區間同樣滿足此性質,證畢。

而且不難證明,第乙個區間對於第二個區間就滿足這樣的性質,數學歸納法完成。

#include#include#include#define  n  51000

#define nn 110000

using namespace std;

inline int mymin(int x,int y)

struct node

tr[nn];int len;

void bt(int l,int r)

}inline void updata(int x)

inline void get_lazy(int x)

inline void downdata(int x)

int change(int now,int l,int r,int ll,int rr,int k)//返回值為改變了

{ int mid=(l+r)>>1,lc=tr[now].l,rc=tr[now].r;

downdata(now);

if(l==ll && r==rr)

{ int val=0;

if(tr[now].d-tr[now].c<=k)val=tr[now].d-tr[now].c,get_lazy(now);

else

{ val=change(rc,mid+1,r,mid+1,rr,k);

if(val>1,lc=tr[now].l,rc=tr[now].r;

if(rr<=mid)return findans(lc,l,mid,ll,rr);

else if(mid但是要注意有一種貪心是錯誤的,即每一次選擇最多集合覆蓋的區域放數字,乙個錯誤資料:

810 11 1

9 12 1

8 13 1

7 14 1

6 15 1

2 10 1

1 3 2

2 7 2

尤其是對於有相同的集合覆蓋數的區域更加難以選擇,因為選擇的錯誤更加容易導致錯誤(反正這種貪心原本就是錯的),比如:

4

1 2 1

2 3 1

3 4 1

4 5 1

第乙個錯誤資料我想了好久才構造出來啊qaq。

演算法 線段樹

幾次的省賽,成績都不是很理想。不過這幾次省賽的給我們留下了很多寶貴的經驗 首先發現的是線段樹,每考必有 今天我們學習的就是線段樹 線段樹的功能是 1 對一段數字進行累加。2 對數字進行搜尋。3 將包含在區間int的元素x插入到樹t中。4 從線段樹中刪除元素x。5 對線段樹上的資料進行更新。今天,我們...

演算法 線段樹

線段樹的根節點是整段區間,其它結點是由區間不斷二分得到的子區間,其中葉子結點是區間的每個單獨的元素。這裡使用結構體存線段樹。struct tree tree 4 maxn 2 注意陣列大小至少要開到區間長度的四倍大這裡預設我們要求的是區間和,故結點值均為區間和。可以視情況改變結點值的含義。void ...

線段樹(區間樹)

目錄 為什麼要使用線段樹 什麼是線段樹 線段樹融合介面 線段樹實現 線段樹例題 融合介面 author administrator param public inte ce merger package com.suanfa.segmenttree 線段樹 區間樹 author administra...