YYHS 猜數字(並查集 線段樹維護)

2022-08-20 17:51:10 字數 1547 閱讀 8998

lyk在玩猜數字遊戲。

總共有n個互不相同的正整數,lyk每次猜一段區間的最小值。形如[li,ri]這段區間的數字的最小值一定等於xi。

我們總能構造出一種方案使得lyk滿意。直到…… lyk自己猜的就是矛盾的!

例如lyk猜[1,3]的最小值是2,[1,4]的最小值是3,這顯然就是矛盾的。

你需要告訴lyk,它第幾次猜數字開始就已經矛盾了。

第一行兩個數n和t,表示有n個數字,lyk猜了t次。

接下來t行,每行三個數分別表示li,ri和xi。

輸出乙個數表示第幾次開始出現矛盾,如果一直沒出現矛盾輸出t+1。

20 4

1 10 7

5 19 7

3 12 8

1 20 1

3資料範圍

對於50%的資料n<=8,t<=10。

對於80%的資料n<=1000,t<=1000。

對於100%的資料1<=n,t<=1000000,1<=li<=ri<=n,1<=xi<=n(但並不保證一開始的所有數都是1~n的)

hint

建議使用讀入優化

inline int read()

這道題我們先考慮矛盾的情況

我們不難發現有以下兩種情況是矛盾的

1.當乙個區間覆蓋了另乙個區間且大的區間的x值比另乙個區間的x值小的時候是矛盾的

2.當兩個區間的x值相同時,如果這兩個區間沒有交集,這也是矛盾的

知道了矛盾的情況後

我們可以二分矛盾的句子的位置

將前k個句子按x值從大到小排個序,然後我們列舉,判斷當前區間的x值和前乙個區間的x值是否相同

如果相同,就判斷一下有沒有交集

如果不相同,我們可以維護乙個線段樹,將交集的區間覆蓋為1,查詢並集的區間是否被覆蓋為1,當然我們也可以用並查集來維護,我是用並查集來做的,但還是感覺線段樹應該好懂一些(雖然**長了些)

1 #include2

#define n 1000005

3using

namespace

std;

4int

n,t,cnt;

5int

fa[n];

6struct

nodea[n],b[n];

9bool cmp(node x,node y)

10int find(int x)

11bool check(int

x)26 lmin=lmax=b[i].l;

27 rmin=rmax=b[i].r;

28 } else35}

36 f1=find(lmax);

37if (f1>rmin) return

true;38

return

false;39

}40intmain() else l=mid+1;52

}53 printf("

%d\n

",ans);

54return0;

55 }

view code

紅綠 線段樹分治, 並查集

對 1,q to t 1,q tot 1,q t ot 進行線段樹分治,將每個 綠綠 的 影響區間分為 log q tot log q tot logq t ot個區間散布在線段樹節點中,其中 qto tq tot qt o t 為詢問的總數 然後對線段樹dfs dfsdf s,合併祖先鏈的和當前節...

線段樹 樹狀陣列 並查集

利用線段樹十分方便的處理區間,線段樹是一棵完美的二叉樹,樹上的每乙個節點都維護乙個區間,根維護的是整個區間,線段樹通常用來計算區間內資料的和或者是修改某處的值。對區間的操作可以再o logn 的時間內完成。下面我們通過 實現線段樹的構建,修改,區間求和。include include 線段樹 def...

poj1456 並查集or線段樹

本來做並查集專題看到的題目,但是卻是用線段樹a掉的,感覺這題用線段樹做挺水的。先將物品按價值降序排序,然後依次查詢,每個物品的最後期限,就相當於給了線段樹查詢範圍,在1 d範圍內找還有沒有空餘的點,有的話則占用,更新線段樹,單點更新,感覺比較簡單。如果用並查集的話,題目將用過的天作為乙個集合,排序之...