離散化模板 洛谷1955 程式自動化分析

2022-02-02 17:54:09 字數 2318 閱讀 4864

這是很久之前做過的題了,也是我第一次接觸離散化的題。之前一直忘了記下來,今天補寫一篇離散化部落格。 

(懶得複製貼上再改格式了,大家直接看吧)

最開始看過一遍題這東西簡單的一批啊,並查集板子吧。先處理相等關係,相等的扔到乙個集子裡,然後判斷不等關係,每個不等關係中的兩個數要是在乙個集子裡就不成立,一遍判斷下來啥事沒有就成立。又能水過一道題了哈哈哈!

開始一寫,笑容漸漸凝固在臉上:等一下這個數的大小小於等於1e9,我的father陣列開不下啊[託腮][託腮]。最開始還不會離散化,想的是開幾個int陣列,用要存的數%每個陣列的大小,分開儲存。比如開10個1e8的陣列,100000005就存在第二個陣列第五個,10就存在第乙個陣列第十個這樣的。後來一想出題人肯定不會是想讓我們這樣的,極大的可能會卡個記憶體啥的,這種方法實際上的記憶體是沒有改變的,所以估計會被卡掉,而且極其麻煩。

再仔細看一看,題目中n<=1e6,描述的每個關係涉及兩個數,那麼最多就涉及2000000個數,那麼就相當於1e9的儲存空間中有大部分是空著的,簡直是在浪費空間,能優化嗎?顯然可以,在這個題中,我們需要的只是區分每乙個數,而不需要每個數的具體大小,那麼我們是不是就可以把一些大一點的數用小一點的數代替呢?就像暗號一樣,反正最後只要保證每個數有專屬於它的暗號,可以區分就可以了。這就是離散化。

那麼具體該怎麼做呢?畢竟之前沒接觸過離散化所以此時我在網上一頓搜尋應該情有可原

那麼,離散化一共包括三部。一、排序。二、去重。三、對映。下面一步一步講解。

這是非常簡單的一步。一邊讀入一邊把所有涉及到的數字存在all陣列裡,然後sort排序就行了(p.s. 可以順便在這裡特判一下乙個不等關係都沒有就直接yes然後continue)。

1 cin>>n;

2 memset(all,0,sizeof

(all));

3int judge=0;4

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

10if(!judge)

11 sort(all+1,all+tot);

這就是之前不會的原因了,這部分涉及兩個之前沒接觸過的函式lower_bound()和unique()(都屬於algorithm庫)。unique的作用是「去掉」容器中重複元素(不一定要求陣列有序),它會把重複的元素新增到容器末尾(所以陣列大小並沒有改變),而返回值是去重之後的尾位址(因此我們可以相當於地認為陣列大小變成了unique(all+1,all+tot)-all-1,後面的元素就都相當於被抹掉了,那麼我們就得到了乙個本題涉及的所有數的不重複列表,這樣的話我們就可以把乙個數的下標直接當成它的「暗號」),而函式lower_bound()在first和last中的前閉後開區間進行二分查詢,返回大於或等於val的第乙個元素位置。如果所有元素都小於val,則返回last的位置(注意它返回的也是位置),通過lower_bound()我們就可快速找到乙個數在all陣列中的位置,然後儲存起來它的下標了。

1

int cnt=unique(all+1,all+tot)-all-1;2

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

最後就直接跑並查集就行了。我認為這就不用再說了吧。

1 #include2

using

namespace

std;

3int all[2000002],fa[20000002];4

struct

ucun[20000002];7

bool

cmp(u a,u b)

10int find(int

x)14

intmain()

29if(!judge)

30 sort(all+1,all+tot);

31int cnt=unique(all+1,all+tot)-all-1;32

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

36for (int i=1;i<=cnt+1;i++) fa[i]=i;

37int js=0

;38 sort(cun+1,cun+1+n,cmp);

39while(1)45

int ans=1;46

for (int i=js;i<=n;i++)53}

54if(ans) cout<

yes"

<

55else cout<

<

57return0;

58 }

view code

這大概是我自學的最好的一回了。unique()和lower_bound()都徹徹底底地查了用法,離散化可以說學清楚了。或許,這就是所謂的「超越教練員」必經的一步吧。

幸甚至哉,歌以詠志。

洛谷 P1955 程式自動分析(並查集 離散化)

分析 首先看到題目中有兩種關係,會想到帶權並查集,但發現並不適用,反而有點複雜,其次看了元素的範圍之後才發現這道題應該就是普通並查集,難點在於對元素進行離散化,使得元素大小縮小到下標可以表示的範圍。include include include includeusing namespace std ...

洛谷P1955 程式自動分析 並查集 離散

給出n nn個變數之間的關係 等或不等 求這些活能否全部是真話。思路 考慮並查集,先將讀入的排序,給出相等關係的在前,不等關係的在後。那麼對於所有相等的兩個變數,我們將它們化為同一集合。之後對於不相等的變數,我們看看這兩個變數是否在同一集合內,如果在同一集合內,說明這兩個變數是相等的,所以肯定不成立...

洛谷P1955 程式自動分析 並查集 離散

給出nn 個變數之間的關係 等或不等 求這些活能否全部是真話。思路 考慮並查集,先將讀入的排序,給出相等關係的在前,不等關係的在後。那麼對於所有相等的兩個變數,我們將它們化為同一集合。之後對於不相等的變數,我們看看這兩個變數是否在同一集合內,如果在同一集合內,說明這兩個變數是相等的,所以肯定不成立 ...