题目链接:http://codeforces.com/gym/102220/problem/H
At the main street of Byteland, there will be built n skyscrapers, standing sequentially one next to other. If look leftside right, sequence of their height will be a1,a2,…,an.
Initially the street is empty, every skyscraper’s height is 0. Hamster is the leader of the construction team. In each stage, Hamster can select a range [l,r], then the team will work on this range. Specifically, assume the height sequence is h1,h2,…,hn, then hl,hl+1,…,hr will increase by 1 during this stage. When hi=ai holds for all i∈[1,n], the project will be closed.
The plan may be changed for many times. There will be m events of 2 kinds below:
1 l r k (1≤l≤r≤n,1≤k≤10e5), for all x∈[l,r], change ax to ax+k.
2 l r (1≤l≤r≤n), assume a1,a2,…,al−1,ar+1,ar+2,…,an=0, ask for the minimum number of required stages to close the project.
Input
The first line of the input contains an integer T(1≤T≤1000), denoting the number of test cases.
In each test case, there are two integers n,m(1≤n,m≤100000)in the first line, denoting the number of skyscrapers and events.
In the second line, there are n integers a1,a2,…,an(1≤ai≤100000).
For the next m lines, each line describes an event.
It is guaranteed that ∑n≤10e6 and ∑m≤10e6.
Output
For each query event, print a single line containing an integer, denoting the answer.
Example
Input
1
5 4
1 3 1 4 5
2 1 5
1 3 4 2
2 2 4
2 1 5
Output
7
6
6
题意:
给定一个长度为n的数组a,有两个操作,操作1是数组a中[l,r]加k,操作2是取数组a中[l,r]为数组w,给定规则,求得到w的最小次数。
规则,给数组h,全为0,每次选一个连续的区间,h在这个区间上的数全部加一,要求最后h=w。
思路:
用一个树状数组bit0存a中相邻两个数的差,再用另一个树状数组bit1存a中相邻两个数的差(bit1存正数差,如果后面一个数减前面一个数大于0,则存下这个正数,否者存0)。
对于操作1,不断更新bit0和bit1;
对于操作2,最小次数=a[l]+sum(bit1,r)-sum(bit1,l)。
参考代码:
#include<iostream>
#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<string>
#include<cstring>
using namespace std;
typedef long long ll;
const int INF=0x3f3f3f3f;
const int MAX_N=100000+5;
int n,m;
ll bit0[MAX_N+2],bit1[MAX_N+2];
ll sum(ll *b, int i){
ll s=0;
while(i>0){
s+=b[i];
i-=i&-i;
}
return s;
}
void add(ll *b,int i,ll x){
while(i<=n){
b[i]+=x;
i+=i&-i;
}
}
ll get(ll *b,int i){
return sum(b,i)-sum(b,i-1);
}
void change(ll *b,int i,ll x){
ll s=get(b,i);
add(b,i,x-s);
}
ll get_length(int i){
return sum(bit0,i);
}
int main(){
int T;
scanf("%d",&T);
while(T--){
memset(bit0,0,sizeof(bit0));
memset(bit1,0,sizeof(bit1));
scanf("%d%d",&n,&m);
ll pre=0;
for(int i=1;i<=n;i++){
ll x;
scanf("%lld",&x);
add(bit0,i,x-pre);
if(x-pre>0){
add(bit1,i,x-pre);
}
pre=x;
}
int t,l,r;
ll k;
while(m--){
scanf("%d",&t);
if(t==1){
scanf("%d%d%lld",&l,&r,&k);
add(bit0,l,k);
add(bit0,r+1,-k);
ll xl=get(bit0,l);
ll xr=get(bit0,r+1);
if(xl>0)change(bit1,l,xl);
else change(bit1,r+1,0);
if(xr>0)change(bit1,r+1,xr);
else change(bit1,r+1,0);
}
else{
scanf("%d%d",&l,&r);
ll res=sum(bit1,r)-sum(bit1,l)+get_length(l);
printf("%lld\n",res);
}
}
}
return 0;
}