This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
#define int long long
int n,k;
int a[N];
long long tree[N*3],trep[N*3],tres[N*3];
void built(int v,int l,int r)
{
if(l > r)
{
return;
}
if(l == r)
{
tree[v] = a[l];
trep[v] = a[l]*l;
tres[v] = a[l]*(n - l + 1);
///cerr << "l == " << l << " " << trep[v] << " " << tres[v] << endl;
return;
}
int mid=(l+r)>>1;
built(v*2,l,mid);
built(v*2 + 1,mid+1,r);
tree[v] = tree[v*2] + tree[v*2 + 1];
trep[v] = trep[v*2] + trep[v*2 + 1];
tres[v] = tres[v*2] + tres[v*2 + 1];
}
long long get(int v,int l,int r,int ml,int mr)
{
if(l > r || ml > r || mr < l)
{
return 0;
}
if(ml <= l && r <= mr)
{
return tree[v];
}
int mid=(l+r)>>1;
return get(v*2 , l , mid , ml , mr) + get(v*2 + 1,mid + 1,r,ml,mr);
}
long long getp(int v,int l,int r,int ml,int mr)
{
if(l > r || ml > r || mr < l)
{
return 0;
}
if(ml <= l && r <= mr)
{
return trep[v];
}
int mid=(l+r)>>1;
return getp(v*2 , l , mid , ml , mr) + getp(v*2 + 1,mid + 1,r,ml,mr);
}
long long gets(int v,int l,int r,int ml,int mr)
{
if(l > r || ml > r || mr < l)
{
return 0;
}
if(ml <= l && r <= mr)
{
return tres[v];
}
int mid=(l+r)>>1;
return gets(v*2 , l , mid , ml , mr) + gets(v*2 + 1,mid + 1,r,ml,mr);
}
void update(int v,int l,int r,int ind,int val)
{
if(l > r)
{
return;
}
if(l == r)
{
a[l] = val;
tree[v] = a[l];
trep[v] = a[l]*l;
tres[v] = a[l]*(n - l + 1);
///cerr << "l == " << ind << " " << trep[v] << " " << tres[v] << endl;
return;
}
int mid=(l+r)>>1;
if(ind <= mid){
update(v*2,l,mid,ind,val);
}
else{
update(v*2 + 1,mid+1,r,ind,val);
}
tree[v] = tree[v*2] + tree[v*2 + 1];
trep[v] = trep[v*2] + trep[v*2 + 1];
tres[v] = tres[v*2] + tres[v*2 + 1];
}
long long prf(int l, int r){
///мы хотим посчитать 1 + 2 + 3... на подотрезке, возьмем преффиксную сумму на этом подотрезке
long long sum = getp(1,1,n,l,r);
///cerr <<"pre "<< sum<<endl;
///assert(sum == sum2);
///теперь отнимем сумму на подотрезке
sum -= (l - 1) * (get(1, 1, n, l, r));
return sum;
}
long long syf(int l, int r){
///полностью зеркальная функция
long long sum = gets(1,1,n,l,r);
///cerr << "suf "<< sum <<endl;
///assert(sum == sum2);
sum -= (n - r) * get(1, 1, n, l, r);
return sum;
}
int32_t main(){
cin>>n>>k;
for(int i=1;i<=n;i++){
cin>>a[i];
}
built(1,1,n);
int q;
cin>>q;
while(q--)
{
int ty;
cin>>ty;
if(ty == 2){
int l,r;
long long m;
cin>>l>>r>>m;
assert(r >= l);
if((r - l + 1) >= m*2){
///первый случай когда m слишком маленький, в таком случае нужно посчитать 1 + 2 + ... m - 1
assert(l + m - 1 <= r - m + 1);
long long res = get(1,1,n,l + (m - 1) , r - (m - 1))*m;
///вот тут мы посчитали середину
///теперь нужно добавить 1 + 2 + ... m - 1
///давай реализуем функцию prf(l, r) которая будет уметь считать 1 + 2...,
///а так же такую же функцию syf которая будет уметь считать 2 + 1 ...
///так как очень много одинаковых блоков кода где может быть ошибка
assert(l + m - 2 <= r - m + 2);
res += prf(l, l + m - 2);
res += syf(r - m + 2, r);
cout << res << endl;
}
else{
int cur_m = r - l + 2 - m;
assert(cur_m <= m && cur_m > 0);
///cur_m
long long res = 0;
///assert(l + cur_m == r - cur_m);
res += prf(l, l + cur_m - 1);
res += syf(r - cur_m + 1, r);
///cerr << r - cur_m << " " << l + cur_m << endl;
res += get(1, 1, n, l + cur_m, r - cur_m) * cur_m;
///cerr<<"3 ";
cout << res << endl;
}
}
else{
vector<int>ind;
for(int i=0;i<k;i++){
int x;
cin>>x;
ind.push_back(x);
}
int fi = a[ind[0]];
for(int i=1;i<k;i++){
update(1,1,n,ind[i-1],a[ind[i]]);
}
update(1,1,n,ind[k-1],fi);
}
}
}
/*
2 3 4 5 6 7
9 5 1 6 3 4
1 2 3 3 2 1
9 + 10 + 3 + 18 + 6 + 4 = 20 +
8 5
1 1 1 1 1 1 1 1
1
2 1 8 5
*/
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |