bzoj 1798 線段樹 雙lazy標記

2021-06-26 23:27:15 字數 2343 閱讀 3514

time limit: 30 sec  

memory limit: 64 mb

submit: 2645  

solved: 984 [

submit][

status]

老師交給小可可乙個維護數列的任務,現在小可可希望你來幫他完成。 有長為n的數列,不妨設為a1,a2,…,an 。有如下三種操作形式: (1)把數列中的一段數全部乘乙個值; (2)把數列中的一段數全部加乙個值; (3)詢問數列中的一段數的和,由於答案可能很大,你只需輸出這個數模p的值。

第一行兩個整數n和p(1≤p≤1000000000)。第二行含有n個非負整數,從左到右依次為a1,a2,…,an, (0≤ai≤1000000000,1≤i≤n)。第三行有乙個整數m,表示操作總數。從第四行開始每行描述乙個操作,輸入的操作有以下三種形式: 操作1:「1 t g c」(不含雙引號)。表示把所有滿足t≤i≤g的ai改為ai×c (1≤t≤g≤n,0≤c≤1000000000)。 操作2:「2 t g c」(不含雙引號)。表示把所有滿足t≤i≤g的ai改為ai+c (1≤t≤g≤n,0≤c≤1000000000)。 操作3:「3 t g」(不含雙引號)。詢問所有滿足t≤i≤g的ai的和模p的值 (1≤t≤g≤n)。 同一行相鄰兩數之間用乙個空格隔開,每行開頭和末尾沒有多餘空格。

對每個操作3,按照它在輸入中出現的順序,依次輸出一行乙個整數表示詢問結果。

7 43

1 2 3 4 5 6 7

51 2 5 5

3 2 4

2 3 7 9

3 1 3

3 4 7235

8【樣例說明】

初始時數列為(1,2,3,4,5,6,7)。

經過第1次操作後,數列為(1,10,15,20,25,6,7)。

對第2次操作,和為10+15+20=45,模43的結果是2。

經過第3次操作後,數列為(1,10,24,29,34,15,16}

對第4次操作,和為1+10+24=35,模43的結果是35。

對第5次操作,和為29+34+15+16=94,模43的結果是8。

測試資料規模如下表所示

資料編號 1 2 3 4 5 6 7 8 9 10

n= 10 1000 1000 10000 60000 70000 80000 90000 100000 100000

m= 10 1000 1000 10000 60000 70000 80000 90000 100000 100000

day1

有乘和加兩種操作,求的是區間和

#includetypedef long long ll;

#define n 100005

struct node

}a[n*4];

ll p,val[n];

void pushdown(ll t)

void build(ll x,ll y,ll t)

ll mid=(x+y)>>1,temp=t<<1;

build(x,mid,temp);

build(mid+1,y,temp+1);

a[t].sum=(a[temp].sum+a[temp+1].sum)%p;

}void update(ll t,ll x,ll y,ll c,ll op)

else

return ;

}if(a[t].add!=0||a[t].mul!=1)

pushdown(t);

ll mid=(a[t].x+a[t].y)>>1,temp=t<<1;

if(x>mid)

update(temp+1,x,y,c,op);

else if(y<=mid)

update(temp,x,y,c,op);

else

a[t].sum=(a[temp].sum+a[temp+1].sum)%p;

}ll find(ll t,ll x,ll y)

if(a[t].add!=0||a[t].mul!=1)

pushdown(t);

ll mid=(a[t].x+a[t].y)>>1,temp=t<<1;

if(x>mid)

ans=find(temp+1,x,y);

else if(y<=mid)

ans=find(temp,x,y);

else

ans=(find(temp,x,mid)+find(temp+1,mid+1,y))%p;

a[t].sum=(a[temp].sum+a[temp+1].sum)%p;

return ans;

}int main()

else}}

return 0;

}

BZOJ 1798 維護序列

線段樹 這 d 道 q 題 s 告訴我說 你沒學過線段樹 嗯 這題要好好想想 qaq 來吧首先要明確的事情是 delta now 記錄的是已經對當前點做過的,但是還沒有對當前點的兒子做過的操作 嗯 我們就這樣 慢慢的退一下 嗯 標記是給兒子用的 嗯 是給兒子用的 奉獻精神 然後,對於這個題,我們可以...

BZOJ 1798, 維護序列

傳送門 維護乙個數列,要求支援區間加 區間乘以及查詢操作。很裸的線段樹,難點在於加法和乘法的操作順序。標記下傳時應先打乘法標記,再打加法標記,同時更新時還要用乘法標記維護加法標記。include typedef long long ll const int n 100005 int n,p,m,x,...

BZOJ 4756 線段樹合併(線段樹)

思路 1.最裸的線段樹合併 2.我們可以觀察到子樹求乙個東西 那我們直接dfs序好了 入隊的時候統計一下有多少比他大的 出的時候統計一下 減一下 搞定 線段樹合併 by siriusren include include include using namespace std const int n...