P4097 【模板】李超線段樹 / [HEOI2013] Segment 題解

題意

有一個平面直角坐標系,總共 n n n 個操作,每個操作有兩種:

  • 給定正整數 x 0 , y 0 , x 1 , y 1 x_0,y_0,x_1,y_1 x0?,y0?,x1?,y1? 表示一條線段的兩個端點。你需要在平面上加入這一條線段,第 i i i 條被插入的線段的標號為 i i i
  • 給定正整數 k k k,問與直線 x = k x=k x=k? 相交的線段中,交點的縱坐標最大的線段的編號。

解法

需要用到線段樹的一個變體:李超線段樹。我們將操作轉化一下:

  • 加入一個一次函數,定義域為 [ l , r ] [l,r] [l,r](這個一次函數畫出的線段,左端點橫坐標為 l l l,右端點橫坐標為 r r r);
  • 給定 k k k,在所有 l ≤ k ≤ r l\le k\le r lkr 的一次函數中,找到在 x = k x=k x=k 處取值最大的那個函數(意思就是在橫坐標為 k k k、垂直于 y y y 軸的直線上,找到 y y y 坐標最高的交點)。

來看一個例子:

在這里插入圖片描述

因為我們總是取 y y y 坐標最高的交點作為答案,所以真正取到答案的部分長這樣:

在這里插入圖片描述

  • 圖中黑色部分即為答案。

那如何在線段樹上維護這個東西呢?我們考慮線段樹上被兩條線段完全覆蓋的一個部分為 [ l , r ] [l,r] [l,r] 的節點的情況:

在這里插入圖片描述

  • 圖中紅藍色為兩個一次函數的圖像、橙色為對答案有貢獻的部分、深灰色為 m i d = ? l + r 2 ? mid=\lfloor\cfrac{l+r}{2}\rfloor mid=?2l+r??、淺灰色為轉折點。李超線段樹的每個節點都會維護當前區間中優勢最大的線段(圖中紅色的線段),因而李超線段樹需要標記永久化

其中,紅色線段(記為 g g g)先被加入,顯然整個線段在當時就是最優的;藍色線段(記為 f f f)然后被加入。此時深紅色的部分沒有受到影響, g g g 仍然優勢最大;但淺藍色部分答案改變。我們將其分為兩個子區間(而 m i d mid mid 左右的區間另稱為左/右區間),可以發現一定有一個子區間被左或右區間完全包含(淺藍色被右區間包含),即在兩條線段中,肯定有一條線段只可能成為左或右區間的答案 f f f 只可能成為右區間最優的線段)。

我們不妨令,在 m i d mid mid f f f 不如 g g g 優(反之交換兩條線段即可),則:

  • 若在左端點處 f f f 更優,那么 f f f g g g 會在左半區間中產生交點, f f f 只有在左區間才可能優于 g g g,于是遞歸到左兒子中進行下傳;
  • 反之,若在右端點處 f f f 更優,那么交點在右半區間中產生,遞歸到右兒子進行下傳(圖中的情況);
  • 如果左右端點 g g g 都更優,那么 f f f 不可能成為答案,不需要下傳(即 g g g 整個在 f f f?? 的上方)。

當交點正好就在 m i d mid mid 上時,我們直接將其歸入 m i d mid mid f f f 不如 g g g 優的情況。這樣我們就完成了對完全覆蓋的區間的修改。對于其他部分覆蓋的區間直接遞歸左右兒子解決即可。對于查詢操作,將自己的答案與左右兒子取個 min ? \min min 返回。

因為每次修改操作都需要遞歸左右兒子,所以加線段的復雜度是 O ( log ? 2 n ) O(\log^2n) O(log2n) 的。

代碼

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
const int maxm = 40000;
struct Line {double k,b;
} L[maxn]; int cnt;
void addLine(int x0,int y0,int x1,int y1) {// 加入一條線段if (x0 == x1) L[++ cnt] = Line {0,max(y0,y1) * 1.0};else {double X = x1 - x0, Y = y1 - y0;L[++ cnt].k = Y / X, L[cnt].b = y0 - Y / X * x0;}
}
const double eps = 1e-9;
namespace LiChaoSegmentTree {#define lson l,mid,rt << 1#define rson mid + 1,r,rt << 1 | 1double K(int u,int d) {return L[u].b + L[u].k * d;}int check(double X,double Y) {return X - Y > eps ? 1 : Y - X > eps ? -1 : 0;}int ans[(maxm << 2) + 5];void color(int l,int r,int rt,int u) {int mid = l + r >> 1;int cM = check(K(u,mid), K(ans[rt],mid)); // 計算中點誰占優勢if (cM == 1 || (cM == 0 && u < ans[rt])) // 總是令新線段不如舊線段優swap(u,ans[rt]); // 把自己更新好int cL = check(K(u,l),K(ans[rt],l));int cR = check(K(u,r),K(ans[rt],r));// 選擇新線段可能更新的區域遞歸if (cL == 1 || (cL == 0 && u < ans[rt])) color(lson,u);if (cR == 1 || (cR == 0 && u < ans[rt])) color(rson,u);}int nowl,nowr;void modify(int l,int r,int rt,int u) {if (nowl <= l && r <= nowr)return color(l,r,rt,u);int mid = l + r >> 1;if (nowl <= mid) modify(lson,u);if (mid < nowr) modify(rson,u);}struct Answer { // 返回的答案int id; double val;bool operator<(const Answer &oth) const {int c = check(val,oth.val);return c == -1 ? 1 : c == 1 ? 0 : id > oth.id;}Answer(int X = 0,double Y = 0.0) { id = X, val = Y; }};int now;Answer query(int l,int r,int rt) { // 標記永久化,所以一路上需要不斷地和自己的值取 maxif (l == r) return Answer{ans[rt],K(ans[rt],now)};int mid = l + r >> 1; Answer res(ans[rt],K(ans[rt],now));if (now <= mid) return max(query(lson),res);else return max(query(rson),res);}
} using namespace LiChaoSegmentTree;
int n,tmp;
const int P = 39989, Q = 1e9;
int chg(int X,int p) { return (X + tmp - 1 + p) % p + 1;
}
int main() {scanf("%d",&n);for (int i = 1,op,x0,x1,y0,y1,x;i <= n;i ++) {scanf("%d",&op);if (op == 1) {scanf("%d%d%d%d",&x0,&y0,&x1,&y1);x0 = chg(x0,P), x1 = chg(x1,P), y0 = chg(y0,Q), y1 = chg(y1,Q);if (x0 > x1) swap(x0,x1), swap(y0,y1);nowl = x0, nowr = x1;addLine(x0,y0,x1,y1);modify(1,maxm,1,cnt); } else {scanf("%d",&x), x = now = chg(x,P);printf("%d\n",tmp = query(1,maxm,1).id);}} return 0;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/15868.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/15868.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/15868.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Photoshop插件(UXP)編寫過程中,如何更新sp-checkbox的選中狀態

?問題說明 sp-checkbox是uxpSpectrum UXP Widgets下的一個小組件&#xff0c;內置樣式大概是這樣&#xff1a; 那么&#xff0c;如果用js動態的改變選中的狀態&#xff0c;應該如何做呢&#xff1f; 如果直接是html來寫&#xff1a; <sp-checkbox checked>Checked<…

特斯拉FSD的「端到端」到底能不能成?

引言 近年來&#xff0c;特斯拉的全自動駕駛&#xff08;Full Self-Driving&#xff0c;FSD&#xff09;技術備受關注&#xff0c;尤其是其「端到端」的AI軟件框架更是引發了廣泛討論。端到端技術到底是一條正確的路徑嗎&#xff1f;它能否真正實現完全自動駕駛&#xff1f;本…

LangChain 0.2 - 矢量存儲和檢索器

本文翻譯整理自&#xff1a;Vector stores and retrievers https://python.langchain.com/v0.2/docs/tutorials/retrievers/ 文章目錄 一、說明概念 二、文件三、Vector stores示例 四、Retrievers五、了解更多 一、說明 本教程將讓您熟悉 LangChain 的向量存儲和檢索器抽象。…

大語言模型LLM 相關知識匯總

大型語言模型&#xff08;LLM&#xff09;在設計和應用時需要遵守一系列的道德和法律標準&#xff0c;以確保不會輸出不當內容。以下是一些LLM通常不應該對外輸出的內容類型&#xff1a; 個人隱私信息&#xff1a;包括但不限于個人身份信息&#xff08;PII&#xff09;&#x…

Echarts 實現將X軸放在圖表頂部并且自動播放展示提示信息內容

文章目錄 需求分析效果預覽需求 如下圖所示,實現柱狀圖中反轉倒著繪制 分析 使用 ECharts 來實現對 Y 軸的倒序排序時,可以通過設置 yAxis 的 inverse 屬性為 true 來實現。以下是一個簡單的示例,演示了如何使用 ECharts 來創建一個柱狀圖,并將 Y 軸進行倒序排序:并且…

前綴和算法:提升編程效率的秘密武器(Java版)

本篇會加入個人的所謂魚式瘋言 ??????魚式瘋言:??????此瘋言非彼瘋言 而是理解過并總結出來通俗易懂的大白話, 小編會盡可能的在每個概念后插入魚式瘋言,幫助大家理解的. &#x1f92d;&#x1f92d;&#x1f92d;可能說的不是那么嚴謹.但小編初心是能讓更多人能接…

代碼審計--一道簡單的文件包含題目的多種利用方式

NO.1 傳統方法 首先來看下代碼 <?php error_reporting(0); if(isset($_GET["file"])){include($_GET["file"]); }else{highlight_file(__FILE__);phpinfo(); } ?>看完代碼后再來學習學習函數吧&#xff0c;畢竟菜啊&#xff01;&#xff01;&…

IronPython和C#交互

在C#環境中動態調用IronPython腳本&#xff0c;可以通過以下步驟實現&#xff1a; 安裝IronPython: 首先&#xff0c;確保你的項目中已經安裝了IronPython。可以通過NuGet包管理器來安裝IronPython。 創建IronPython運行環境: 在C#代碼中&#xff0c;你需要創建一個ScriptEngi…

NASA數據集——阿爾法噴氣式大氣實驗甲醛(HCHO)數據

Alpha Jet Atmospheric eXperiment Formaldehyde Data 簡介 阿爾法噴氣式大氣實驗甲醛數據 阿爾法噴氣式大氣實驗&#xff08;AJAX&#xff09;是美國國家航空航天局艾姆斯研究中心與 H211, L.L.C. 公司的合作項目&#xff0c;旨在促進對加利福尼亞、內華達和太平洋沿岸地區的…

【NOIP2014普及組復賽】題4:子矩陣

題3&#xff1a;子矩陣 【題目描述】 給出如下定義&#xff1a; 1.子矩陣&#xff1a;從一個矩陣當中選取某些行和某些列交叉位置所組成的新矩陣&#xff08;保持行與列的相對順序&#xff09;被稱為原矩陣的一個子矩陣。 例如&#xff0c;下面左圖中選取第 2 、 4 2、4 2、…

vue項目中使用json編輯器

實現效果&#xff1a; 借助插件json-editor-vue3實現效果如圖一&#xff0c;如果嫌丑可以通過類名改一下樣式如圖二。 實現過程&#xff1a; 安裝插件&#xff1a;npm install json-editor-vue3 文檔鏈接&#xff1a;GitCode - 開發者的代碼家園 <script setup name&quo…

Golang發送POST請求并傳遞JSON數據

客戶端 package mainimport ("c02_get_param/common""fmt""zdpgo_resty" )func main() {// Create a Resty Clientclient : zdpgo_resty.New()// 設置字符串resp, err : client.R().SetHeader("Content-Type", "application/jso…

AcWing 3466. 清點代碼庫(STL:map,vector)

3466. 清點代碼庫 需要求有幾種不同數列&#xff0c;每種有多少個&#xff0c;可以想到用map。它的鍵是一個數列&#xff0c;可以把它放在vector里。也就是map<vector<int>,int> 要滿足要求的輸出序列&#xff0c;就要想把它放在其他容器&#xff0c;或數組里&…

mac清理緩存的命令

mac清理緩存的命令 在macOS中&#xff0c;你可以使用以下命令來清理緩存&#xff1a; 清理DNS緩存&#xff1a; sudo killall -HUP mDNSResponder 清理Metal緩存&#xff1a; mkdir ~/Library/Caches/com.apple.Metal 清理文件系統元數據緩存&#xff1a; sudo find /private/…

Vite + Vue3 部署 GitHub

因為靜態資源是可以部署到 GitHub 上&#xff0c;自己順便學習部署網站 因為我使用的是 Vite 工具&#xff0c;官方有提供相應 Demo 部署靜態站點 | Vite 官方中文文檔 新建文件夾 .github 然后再建一個文件夾 workflows 新建文件 main.yml 文件 直接使用官方文檔 demo #…

什么是spring 的組件掃描?

Spring的組件掃描&#xff08;Component Scanning&#xff09;是Spring框架提供的一種機制&#xff0c;用于自動尋找和注冊應用程序中的組件&#xff0c;進而減少顯式的配置。這些組件通常是標有特定注解&#xff08;如Component, Service, Repository, Controller等&#xff0…

如何處理時間序列的缺失數據

您是否應該刪除、插入或估算&#xff1f; 世界上沒有完美的數據集。每個數據科學家在數據探索過程中都會有這樣的感覺&#xff1a; df.info()看到類似這樣的內容&#xff1a; 大多數 ML 模型無法處理 NaN 或空值&#xff0c;因此如果您的特征或目標包含這些值&#xff0c;則在…

Java-MySql:JDBC

目錄 JDBC概述 JDBC搭建 1、導入mysql開發商提供的jar包 2、注冊驅動 3、與數據庫連接 注解&#xff1a; Statement&#xff1a; 代碼 運行 PreparedStatement&#xff1a; 代碼 運行 PreparedStatement和Statement Statement 增 代碼 運行 刪 代碼 運…

九、圖形化腳本

多年來&#xff0c; shell腳本一直都被認為是枯燥乏味的。但如果你準備在圖形化環境中運行腳本時&#xff0c;就未必如此了。有很多與腳本用戶交互的方式并不依賴read和echo語句。 9.1 創建文本菜單 創建交互式shell腳本最常用的方法是使用菜單。提供各種選項可以幫助腳本用戶…

AI遇上遙感,未來會怎樣?

隨著航空、航天、近地空間等多個遙感平臺的不斷發展&#xff0c;近年來遙感技術突飛猛進。由此&#xff0c;遙感數據的空間、時間、光譜分辨率不斷提高&#xff0c;數據量也大幅增長&#xff0c;使其越來越具有大數據特征。對于相關研究而言&#xff0c;遙感大數據的出現為其提…