(分塊)洛谷 P2801 教主的魔法 題解

之前學過 莫隊 算法,其運用了分塊思想;但是我居然是第一次寫純種的分塊題目。

題意

給你一個長度為 n n n 的序列 a a a(一開始 ? a i ∈ [ 1 , 1000 ] \forall a_i\in[1,1000] ?ai?[1,1000])。要求執行 q q q 次操作,操作有兩種,每次形如 o p , l , r , w / c op,l,r,w/c op,l,r,w/c

  • o p op op M \rm M M,將 a l , a l + 1 , ? , a r a_l,a_{l+1},\cdots,a_r al?,al+1?,?,ar? 分別加上 w w w
  • o p op op A \rm A A,查詢 a l , a l + 1 , ? , a r a_l,a_{l+1},\cdots,a_r al?,al+1?,?,ar? 中,有多少個數大于 c c c

n ≤ 1 0 6 , q ≤ 3000 , w ≤ 1000 , c ≤ 1 0 9 n\le10^6,q\le3000,w\le1000,c\le10^9 n106,q3000,w1000,c109

思路

主席樹?是我早就不會打的。

如果我們把它變成一道分塊練習題呢?

考慮對序列 a a a 分塊,對于每一塊內,使用輔助數組 b b b 以保證塊內數有序。不妨設 b l t , b r t bl_t,br_t blt?,brt? 表示塊 t t t 的左右端點, b e l i bel_i beli? 表示下標 i i i 所在的塊的編號。

對于修改操作 l , r , w l,r,w l,r,w,如果 ? t , b l t ≤ l < r ≤ b r t \exist t,bl_t\le l<r\le br_t ?t,blt?l<rbrt?,即同一塊, t = b e l l = b e l r t=bel_l=bel_r t=bell?=belr?,如果其不在左右端點上,那么塊內的排序性質就會被破壞;反之如果它們不在同一塊,說明它們中間跨過了若干塊整塊的區間,我們發現被跨過的區間仍然保持有序

那么我們得到一個初步的修改方法:

  • 設左右端點所在的塊分別在 l b = b e l l , r b = b e l r lb=bel_l,rb=bel_r lb=bell?,rb=belr?,如果 l b = r b lb=rb lb=rb,就塊內暴力加 w w w 并快排更新;
  • 否則即 l b < r b lb<rb lb<rb,我們發現塊 l b + 1 ~ r b ? 1 lb+1\sim rb-1 lb+1rb?1 內仍然有序,那么不妨想線段樹引入懶惰標記一樣,我們搞一個加法標記,把整一塊 t t t 內所有元素同時加的數,用 t a g t tag_t tagt? 記錄下來,等到查詢時再處理;只強制更新更新 l ~ b r l b l\sim br_{lb} lbrlb? b l r b ~ r bl_{rb}\sim r blrb?r 的數據和塊 l b , r b lb,rb lb,rb

這樣子大大減少了排序的次數,每次修改操作頂多 2 × log ? 2 n 2\times \log_2n 2×log2?n,瓶頸在于快排。

void modify(ll t)//更新t塊內數據
{for(int i=bl[t];i<=br[t];i++)b[i]=a[i];sort(b+bl[t],b+br[t]+1);
}
void add(ll ql,ll qr,ll x)//l,r,w
{ll lb=bel[ql],rb=bel[qr];//左右端所在塊if(lb==rb)//同一塊{for(int i=ql;i<=qr;i++)a[i]+=x;modify(lb);return;}//不同塊for(int i=ql;i<=br[lb];i++)a[i]+=x;for(int i=bl[rb];i<=qr;i++)a[i]+=x;modify(lb);modify(rb);for(int i=lb+1;i<rb;i++)//lb+1~rb-1塊打標記tag[i]+=x;
}

接下來就是查詢,其實就和修改所運用的思想差不多了。同樣討論 l , r l,r l,r 在或不在同一塊的兩種情況。如果同一塊就直接 q l ~ q r ql\sim qr qlqr 掃過去(倒著枚舉提前 break 凹時間也行、甚至乎二分,反正塊上數組 b b b 就是有序的),不同塊就搜左右兩邊 l ~ b r r b l\sim br_{rb} lbrrb? b l r b ~ r bl_{rb}\sim r blrb?r(這里不能二分,因為原數組并非有序),至于中間的整塊整塊的,按塊二分就好。

ll find(ll ql,ll qr,ll x)
{ll l=ql,r=qr;while(l<=r){ll mid=(l+r)>>1;if(b[mid]<x)l=mid+1;else r=mid-1;}return qr-l+1;
}
ll query(ll ql,ll qr,ll x)
{ll ret=0,lb=bel[ql],rb=bel[qr];if(lb==rb){ret+=find(ql,qr,x-tag[lb]);return ret;}for(int i=ql;i<=br[lb];i++)if(a[i]+tag[lb]>=x)ret++;for(int i=bl[rb];i<=qr;i++)if(a[i]+tag[rb]>=x)ret++;for(int i=lb+1;i<rb;i++)ret+=find(bl[i],br[i],x-tag[i]);return ret;
}

塊長 n \sqrt{n} n ?,修改一次是塊長+塊內排序,查詢是 塊內二分 或 塊長掃左右端+塊數*塊內二分,時間復雜度 Θ ( m n + m n log ? 2 n ) = Θ ( m n log ? 2 n ) \Theta(m\sqrt{n}+m\sqrt{n}\log_2\sqrt{n})=\Theta(m\sqrt{n}\log_2\sqrt{n}) Θ(mn ?+mn ?log2?n ?)=Θ(mn ?log2?n ?)

代碼

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll N=1e6+9;
ll n,q,a[N];
ll tag[N];//加法標記
ll bSize,cnt_b,bel[N],bl[N],br[N],b[N];
void init()
{bSize=sqrt(n);cnt_b=n/bSize;if(n%bSize)cnt_b++;for(int i=1;i<=n;i++){bel[i]=(i-1)/bSize+1;b[i]=a[i];}for(int i=1;i<=cnt_b;i++){bl[i]=(i-1)*bSize+1;br[i]=i*bSize;}br[cnt_b]=n;for(int i=1;i<=cnt_b;i++)sort(b+bl[i],b+br[i]+1);
}
void modify(ll t)//更新t塊內數據
{for(int i=bl[t];i<=br[t];i++)b[i]=a[i];sort(b+bl[t],b+br[t]+1);
}
void add(ll ql,ll qr,ll x)
{ll lb=bel[ql],rb=bel[qr];//左右端所在塊if(lb==rb)//同一塊{for(int i=ql;i<=qr;i++)a[i]+=x;modify(lb);return;}//不同塊for(int i=ql;i<=br[lb];i++)a[i]+=x;for(int i=bl[rb];i<=qr;i++)a[i]+=x;modify(lb);modify(rb);for(int i=lb+1;i<rb;i++)//lb+1~rb-1塊打標記tag[i]+=x;
}
ll find(ll ql,ll qr,ll x)
{ll l=ql,r=qr;while(l<=r){ll mid=(l+r)>>1;if(b[mid]<x)l=mid+1;else r=mid-1;}return qr-l+1;
}
ll query(ll ql,ll qr,ll x)
{ll ret=0,lb=bel[ql],rb=bel[qr];if(lb==rb){ret+=find(ql,qr,x-tag[lb]);return ret;}for(int i=ql;i<=br[lb];i++)if(a[i]+tag[lb]>=x)ret++;for(int i=bl[rb];i<=qr;i++)if(a[i]+tag[rb]>=x)ret++;for(int i=lb+1;i<rb;i++)ret+=find(bl[i],br[i],x-tag[i]);return ret;
}
int main()
{scanf("%lld%lld",&n,&q);for(int i=1;i<=n;i++)scanf("%lld",&a[i]);init();while(q--){char op;ll l,r,x;cin>>op;scanf("%lld%lld%lld",&l,&r,&x);if(op=='M')add(l,r,x);else printf("%lld\n",query(l,r,x));}return 0;
}

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

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

相關文章

谷歌Chrome或微軟Edge瀏覽器修改網頁任意內容

在谷歌或微軟瀏覽器按F12&#xff0c;打開開發者工具&#xff0c;切換到console選項卡&#xff1a; 在下面的輸入行輸入下面的命令回車&#xff1a; document.body.contentEditable"true"效果如下&#xff1a;

【生日蛋糕——DFS剪枝優化】

題目 分析 代碼 #include <bits/stdc.h> using namespace std;const int N 24; const int inf 0x3f3f3f3f;int mins[N], minv[N]; int R[N], H[N]; int n, m, ans inf;void dfs(int u, int v, int s) {if(v minv[u] > n) return;if(s mins[u] > ans) return;…

【C++基礎十】泛型編程(模板初階)

【C基礎十】泛型編程—模板 1.什么是模板2.函數模板的實例化&#xff1a;2.1隱式實例化2.2顯示實例化 3.函數模板參數的匹配規則4.什么是類模板5.類模板的實例化6.聲明和定義分離 1.什么是模板 void swap(int& a, int& b) {int tmp 0;tmp a;a b;b tmp; }void swap…

如何修復 Tauri 發布后程序運行時顯示 `asset not found: index.html` 的問題

如何修復 Tauri 發布后程序運行時顯示 asset not found: index.html 的問題 在使用 Tauri 發布應用程序時&#xff0c;如果運行時出現 asset not found: index.html 的錯誤&#xff0c;通常是因為 Tauri 無法找到或正確加載前端資源文件&#xff08;如 index.html&#xff09;…

短視頻下載去水印,用什么工具好?

去除視頻和圖片水印是許多用戶的需求&#xff0c;尤其是在分享或保存內容時。以下是6款超好用的工具&#xff0c;幫助你輕松去除水印&#xff0c;享受純凈的視覺體驗&#xff1a; 1. 易下載去水印小程序 特點&#xff1a; 操作簡單&#xff0c;支持抖音、快手、小紅書、嗶哩嗶哩…

【華為OD-E卷 -121 消消樂游戲 100分(python、java、c++、js、c)】

【華為OD-E卷 - 消消樂游戲 100分(python、java、c++、js、c)】 題目 游戲規則:輸入一個只包含英文字母的字符串,字符串中的兩個字母如果相鄰且相同,就可以消除。 在字符串上反復執行消除的動作,直到無法繼續消除為止,此時游戲結束。 輸出最終得到的字符串長度 輸入描…

設計模式(行為型)-備忘錄模式

目錄 定義 類圖 角色 角色詳解 &#xff08;一&#xff09;發起人角色&#xff08;Originator&#xff09;? &#xff08;二&#xff09;備忘錄角色&#xff08;Memento&#xff09;? &#xff08;三&#xff09;備忘錄管理員角色&#xff08;Caretaker&#xff09;?…

YOLO簡史:從YOLOv1到YOLOv12的技術革新與演進

YOLO&#xff08;You Only Look Once&#xff09;系列算法自2015年誕生以來&#xff0c;憑借其“單次推理”的高效特性&#xff0c;徹底改變了目標檢測領域。從初代YOLO到最新的YOLOv12&#xff0c;每一次迭代都凝聚了研究者的智慧與工業界的實踐需求。本文梳理各版本的特性、技…

【技術報告】谷歌開源多模態大模型 Gemma-3

【技術報告】谷歌開源多模態大模型 Gemma-3 1. Gemma-3 簡介1.1 Gemma-3 的新功能1.2 與現有工作流的集成1.3 開始使用 Gemma-3 Gemma-3 技術報告&#xff1a;摘要Gemma-3 技術報告&#xff1a;1. 引言Gemma-3 技術報告&#xff1a;2. 模型架構2.1 視覺模態2.2 預訓練2.3 量化感…

[ISP] 人眼中的顏色

相機是如何記錄顏色的&#xff0c;又是如何被顯示器還原的&#xff1f; 相機通過記錄RGB數值然后顯示器顯示RGB數值來實現顏色的記錄和呈現。道理是這么個道理&#xff0c;但實際上各廠家生產的相機對光的響應各不相同&#xff0c;并且不同廠家顯示器對三原色的顯示也天差地別&…

InfiniBand可靠連接(RC)模式:設計原理、核心機制與應用實踐

引言 InfiniBand作為一種高性能網絡互連技術&#xff0c;廣泛應用于超算集群、分布式存儲和金融交易系統等領域。其可靠連接&#xff08;Reliable Connection, RC&#xff09;模式以硬件級的有序性、可靠性和低延遲特性成為關鍵場景的首選。本文結合技術原理、機制對比和實際應…

【網絡】Caddy 服務器如何提供 TLS(Transport Layer Security)(傳輸層安全協議)

這張圖片介紹了 Caddy 服務器如何提供 TLS&#xff08;傳輸層安全協議&#xff09; 支持&#xff0c;確保通信的安全性。以下是對圖片內容的詳細分析 1. Caddy 是什么&#xff1f; Caddy 是一個現代化的 Web 服務器&#xff0c;以其簡單易用和自動化的 HTTPS 支持而聞名。它內…

GHCTF web方向題解

upload?SSTI! import os import refrom flask import Flask, request, jsonify,render_template_string,send_from_directory, abort,redirect from werkzeug.utils import secure_filename import os from werkzeug.utils import secure_filenameapp Flask(__name__)# 配置…

《Python實戰進階》No21:數據存儲:Redis 與 MongoDB 的使用場景

第21集&#xff1a;數據存儲&#xff1a;Redis 與 MongoDB 的使用場景 摘要 在現代應用開發中&#xff0c;數據存儲的選擇直接影響系統的性能、擴展性和成本。Redis 和 MongoDB 是兩種極具代表性的數據庫技術&#xff0c;它們分別擅長解決不同場景下的問題。本文將深入探討 Re…

【Agent】OpenManus-Prompt組件詳細分析

1. 提示詞架構概述 OpenManus 的提示詞組件采用了模塊化設計&#xff0c;為不同類型的智能體提供專門的提示詞模板。每個提示詞模塊通常包含兩種核心提示詞&#xff1a;系統提示詞&#xff08;System Prompt&#xff09;和下一步提示詞&#xff08;Next Step Prompt&#xff0…

藍橋杯刷題周計劃(第三周)

目錄 前言題目一題目代碼題解分析 題目二題目代碼題解分析 題目三題目代碼題解分析 題目四題目代碼題解分析 題目五題目代碼題解分析 題目六題目代碼題解分析 題目七題目代碼題解分析 題目八題目代碼題解分析 題目九題目代碼題解分析 題目十題目代碼題解分析 前言 大家好&#…

mysql學習-常用sql語句

1、安裝mysql參考網上鏈接&#xff0c;進入mysql數據庫 mysql -u root -p 2、數據庫操作 2.1、創建數據庫 create database 數據庫名 default character set utf8; 2.2、顯示所有數據庫 show databases; 2.3、選擇數據庫 use elementInfo; 2.4、刪除數據庫 drop database…

(全)2024下半年真題 系統架構設計師 綜合知識 答案解析01

系統架構設計師第二版教程VIP課程https://edu.csdn.net/course/detail/40283 操作系統 下列選項中不能作為預防死鎖措施的是 。 A. 破壞“循環等待"條件 B. 破壞“不可搶占”條件 C. 破壞“互斥”條件 D. 破壞“請求和保持”條件 答案&#xff1a;C 解析&…

Java泛型程序設計使用方法

Java泛型程序設計是Java語言中一項強大的特性&#xff0c;它允許你編寫更加通用和類型安全的代碼。以下是Java泛型程序設計的使用方法和技巧&#xff1a; 1. 基本概念 泛型類&#xff1a;可以定義一個類&#xff0c;其中的某些類型是參數化的。 public class Box<T> {pr…

LeetCode算法心得——零數組變換IV(0-1背包)

大家好&#xff0c;我是晴天學長&#xff0c;很久很久沒有寫算法題解了&#xff0c;今天開始轉python了。&#x1f4aa;&#x1f4aa;&#x1f4aa; 1&#xff09;統計打字方案數 給你一個長度為 n 的整數數組 nums 和一個二維數組 queries &#xff0c;其中 queries[i] [li, …