M 一道普通題1 (分塊

2022-05-08 04:18:13 字數 1572 閱讀 8257

給出乙個長為 n​n​ 的數列,以及 n​n​ 個操作,操作涉及區間加法,詢問區間內小於某個值 x​x​ 的前驅(比其小的最大元素)。

input

第一行輸入乙個數字 n,1≤n≤100000n,1≤n≤100000。

第二行輸入 nn 個非負整數,第 ii個數字為 ai(0≤ai≤109)ai(0≤ai≤109)以空格隔開。

接下來輸入nn 行詢問,每行輸入四個數字 opt、l、r、c(c>0)opt、l、r、c(c>0),以空格隔開。

若 oopt=0opt=0,表示將位於[l,r][l,r]的之間的數字都加 cc。

若 opt=1opt=1,表示詢問[l,r][l,r]中 cc 的前驅的值(不存在則輸出 −1−1)。

output

對於每次詢問,輸出一行乙個數字表示答案。

保證所有資料在int範圍內

sample input

41 2 2 3

0 1 3 1

1 1 4 4

0 1 2 2

1 1 2 4

sample output3-1

hint

solution:

最初一看到這個題的這種格式就準備用樹狀陣列來做的,可是做到詢問前驅的時候就發現做不好了,然後就瞄了一下了學長的題解,才發現要用分塊做,分塊呢我只知道它的模板,~~~(我真的好菜哎^^),然後我就套模板一寫,可提交就t了,中間又錯了好多次,最後又看了看學長的**,學長是用的vector來存每一塊的數,左右兩端殘塊暴力處理,中間的整塊(如果有的話)一塊塊的處理,這時更新的時候就沒有對原陣列直接+val,而是維護乙個lazy陣列,表示每一塊要加的數是多少,比較的時候用val-lazy[i]與原陣列比較,如果有比它小的最大的數則存在字首,且為找到的原陣列的那個數+lazy[i],否則就沒有。。。。。。。最後明白這才叫分塊嘛,中間一塊一塊的處理,像我最初中間還是乙個乙個點處理,那分塊意義何在。。。。。。。

code:

#include#include#include#include#include#include#includeusing namespace std;

const int maxn=100001;

int belong[maxn],l[maxn],r[maxn],b[maxn];

int lazy[maxn];

int block,num;

int n;

vectors[1010];

void build()

for(int i=1;i<=belong[n];i++) sort(s[i].begin(),s[i].end());

}void update(int ll,int rr,int val)

int query(int ll,int rr,int val)

{ int first=belong[ll];

int last=belong[rr];

int _max=-1;

for(int i=ll;i<=min(r[belong[ll]],rr);i++)

if(b[i]+lazy[belong[i]]

一道演算法題隨筆(1)

迴圈矩陣 第一列和最後一列是相鄰的 求該矩陣中最大子矩陣 就是子矩陣中的元素和最大 輸入的資料在檔案input.txt中讀取,輸出的結果存入output.txt中 輸入資料的格式如下 中間只能乙個空格,否則就不能存入陣列中 41 1 0 2 5 1 3 1 2 2 1 4 7 8 0 5 usr l...

樹鏈差分的一道題

description 給出一棵有向樹,有點權和邊權,定義乙個節點i的答案為以i為根的子樹中有多少j的點權不小於j i的簡單路徑上邊權和,求所有點的答案 input 第一行一整數t表示用例組數,每組用例首先輸入樹上點數n,之後n個整數x i 表示第i個點的點權,最後n 1行每行三個整數u,v,w表示...

DP 分糖果 一道揹包題

你的揹包 傳送門 狀態 f i j k 前i個糖果選j個糖果且差值為k的最大和 有點類似雙塔,不過這次兩塔有獨立性。差值可正可負,我們設定正為f i r i 負為f i 動歸方程就是揹包的方程 不選f i j k f i 1 j k 選 f i j k f i 1 j 1 k f i r i f i...