#include <iostream>
#include <vector>
using namespace std;
#define MAXN 1000001
typedef long long ll;
int arr[MAXN];
vector<pair<ll,ll> > tree;
int N,M,K;
ll init(int node, int start ,int end){
if (start == end) return tree[node].second = arr[start];
int mid = (start +end) / 2;
return tree[node].second = init(node*2,start,mid)+init(node*2+1,mid+1,end);
}
void update(int node ,int start , int end, int left, int right, ll diff){
// lazy가 있을 때 현재 노드 갱신 후, 자식노드에게 전파 및 초기화
if (tree[node].first != 0){
tree[node].second += (end - start + 1)*tree[node].first;
if (start != end){
tree[node*2].first += tree[node].first;
tree[node*2+1].first += tree[node].first;
}
tree[node].first = 0;
}
if (left > end || right < start ) return ;
// 만족하는 조상노드를 찾았을 때
if (left <= start && end <= right) {
tree[node].second += (end-start+1)*diff;
if (start != end){
tree[node*2].first += diff;
tree[node*2+1].first += diff;
}
return;
}
int mid = (start +end)/2;
update(node*2,start,mid,left,right,diff);
update(node*2+1,mid+1,end,left,right,diff);
tree[node].second = tree[node*2].second + tree[node*2+1].second;
}
ll sum(int node, int start, int end, int left, int right){
if (tree[node].first != 0){
tree[node].second += (end - start + 1)*tree[node].first;
if (start != end){
tree[node*2].first += tree[node].first;
tree[node*2+1].first += tree[node].first;
}
tree[node].first = 0;
}
if (left > end || right < start ) return 0;
if (left <= start && end <= right) return tree[node].second;
int mid = (start+end)/2;
return sum(node*2,start,mid,left,right)+sum(node*2+1,mid+1,end,left,right);
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> N >> M >> K;
M += K;
for (int i = 0; i < N; i++){
cin >> arr[i];
}
int h = 1;
while (h<N) h<<=1;
tree = vector<pair<ll,ll> >(h*2);
init(1,0,N-1);
while (M--){
int order;
cin >> order;
if (order==1){
int left, right;
ll diff;
cin >> left >> right >> diff;
update(1,0,N-1,left-1,right-1,diff);
}
else{
int left,right;
cin >> left >> right;
cout << sum(1,0,N-1,left-1,right-1)<<"\n";
}
}
return 0;
}