給出乙個長為 nn 的數列,以及 nn 個操作,操作涉及區間加法,詢問區間內小於某個值 xx 的前驅(比其小的最大元素)。
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...