結果

問題 No.1099 Range Square Sum
ユーザー 増井舜増井舜
提出日時 2020-06-27 14:43:12
言語 C++14
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 247 ms / 2,000 ms
コード長 5,004 bytes
コンパイル時間 1,629 ms
コンパイル使用メモリ 176,524 KB
実行使用メモリ 21,760 KB
最終ジャッジ日時 2024-07-05 09:10:32
合計ジャッジ時間 5,574 ms
ジャッジサーバーID
(参考情報)
judge3 / judge4
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
5,248 KB
testcase_01 AC 2 ms
5,376 KB
testcase_02 AC 2 ms
5,376 KB
testcase_03 AC 2 ms
5,376 KB
testcase_04 AC 2 ms
5,376 KB
testcase_05 AC 2 ms
5,376 KB
testcase_06 AC 2 ms
5,376 KB
testcase_07 AC 2 ms
5,376 KB
testcase_08 AC 2 ms
5,376 KB
testcase_09 AC 2 ms
5,376 KB
testcase_10 AC 2 ms
5,376 KB
testcase_11 AC 3 ms
5,376 KB
testcase_12 AC 4 ms
5,376 KB
testcase_13 AC 3 ms
5,376 KB
testcase_14 AC 3 ms
5,376 KB
testcase_15 AC 4 ms
5,376 KB
testcase_16 AC 3 ms
5,376 KB
testcase_17 AC 4 ms
5,376 KB
testcase_18 AC 3 ms
5,376 KB
testcase_19 AC 3 ms
5,376 KB
testcase_20 AC 3 ms
5,376 KB
testcase_21 AC 241 ms
21,760 KB
testcase_22 AC 242 ms
21,632 KB
testcase_23 AC 247 ms
21,632 KB
testcase_24 AC 243 ms
21,632 KB
testcase_25 AC 246 ms
21,728 KB
testcase_26 AC 212 ms
21,760 KB
testcase_27 AC 208 ms
21,632 KB
testcase_28 AC 212 ms
21,632 KB
testcase_29 AC 211 ms
21,676 KB
testcase_30 AC 207 ms
21,756 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include "bits/stdc++.h"
#include<vector>
#include<iostream>
#include<queue>
#include<algorithm>
#include<map>
#include<set>
#include<iomanip>
#include<assert.h>
#include<unordered_map>
#include<unordered_set>
#include<string>
#include<stack>
#include<complex>
#include<memory>

#pragma warning(disable:4996)
using namespace std;
using ld = long double;
template<class T>
using Table = vector<vector<T>>;
const ld eps=1e-9;
using Graph=vector<vector<int>>;
using ll=long long;
#define WHATS(var)cout<<__LINE__<<' '<<#var<<"="<<var<<endl;
	
template<class S, class T> ostream& operator <<(ostream &os, const pair<S, T> v){
	os << "( " << v.first << ", " << v.second << ")"; return os;
}
template<class T> ostream& operator <<(ostream &os, const vector<T> &v){
	for(int i = 0; i < v.size(); i++){if(i > 0){os << " ";} os << v[i];} return os;
}
template<class T> ostream& operator <<(ostream &os, const vector<vector<T>> &v){
	for(int i = 0; i < v.size(); i++){if(i > 0){os << endl;} os << v[i];} return os;
}
template<class T> ostream& operator <<(ostream &os, const vector<set<T>> &v){
	for(int i = 0; i < v.size(); i++){if(i > 0){os << endl;} os << v[i];} return os;
}
template<class T> ostream& operator <<(ostream &os, const set<T> &v){
	int i=0;
	for(auto it:v){
		if(i > 0){os << ' ';}
		os << it;
		i++;
	} 
	return os;
}

 using Value1=pair<ll,ll>;
 using Value2=ll;
 const Value1 Zero1= make_pair(0,0);
 const Value2 Zero2(0);
 
struct Node {
	Value1 sum;//更新された値. この値を参照する時は評価が完全に完了しているようにする.
	Value2 lazy;	//遅延されている値を保存している
	Node() :sum(Zero1) {
		lazy = Zero2;
	}
};
#include<vector>
struct lazy_segtree {
	int N;
	vector<Node>dat;
	lazy_segtree(int n,vector<Value1>v) :N(1) {
		while (N < n) N *= 2;
		dat.resize(2 * N);
		for (int i = 0; i < v.size(); ++i) {
			dat[i+N].sum = v[i];
		}
		for (int i = N - 1; i >= 1; --i) {
			update_node(i);
		}
	}
 
	Value2 lazy_connect(const Value2 l, const Value2 r) {
		return l+r;
	}
 
	void lazy_func(const int k, const int a, const int b) {
        dat[k].sum.second+=dat[k].lazy*dat[k].lazy*(b-a)+dat[k].lazy*2*dat[k].sum.first;

        dat[k].sum.first+=dat[k].lazy*(b-a);
	}
 
	Value1 connect(const Value1 l, const Value1 r) {
		return make_pair(l.first+r.first,l.second+r.second);
	}
 
	// inlineつけないと大変なことになるよ!(遅い)
	inline void lazy_evaluate_node(int k, int a, int b) {
		lazy_func(k, a, b);
		if (k < N) { // 2*k(左の子番号) < 2*N (節点の数) のイメージで. 末端ノードじゃなきゃ伝搬するのと等価.
			dat[2 * k].lazy = lazy_connect(dat[2 * k].lazy, dat[k].lazy);	//次は君が伝搬してね☆って感じ.
			dat[2 * k + 1].lazy = lazy_connect(dat[2 * k + 1].lazy, dat[k].lazy);
		}
		dat[k].lazy = Zero2;
	}
 
	inline void update_node(int k) { // kの子が既に評価されていることが前提. 末端以外のときしか呼び出さないような位置に書くのでif文要らない.
		dat[k].sum = connect(dat[2 * k].sum, dat[2 * k + 1].sum);
 
	}
 
	// update(l,r,v) := [l,r)を更新する. 区間は0-indexed.
	void update(int l, int r, Value2 v, int k = 1, int a = 0, int b = -1) {
		if (b == -1)b = N;
		if (l < 0 || r < 0)assert(false);
		lazy_evaluate_node(k, a, b); 	// とりあえず辿ったノードは都合がいいので伝搬しとけ精神.
 
		if (b <= l || r <= a) //[a,b)と[l,r)が交差している場合
			return;
		if (l <= a && b <= r) { // [l,r)が[a,b)を完全に含んでいる場合
			dat[k].lazy = lazy_connect(dat[k].lazy, v);
			lazy_evaluate_node(k, a, b); //一回遅延評価しとかないと都合悪いので.
			return;
		}
 
		int m = (a + b) / 2;
		update(l, r, v, 2 * k, a, m);
		update(l, r, v, 2 * k + 1, m, b);
		update_node(k);
	}
	//get(l,r) := [l,r)に対するクエリの答えを得る. 区間は0-indexed.
	Value1 get(int l, int r, int k = 1, int a = 0, int b = -1) {
		if (b == -1)b = N;
 
		if (l < 0 || r<0)assert(false);
		lazy_evaluate_node(k, a, b); // とりあえず辿ったノードは都合がいいので伝搬しとけ精神.
 
		if (b <= l || r <= a) //[a,b)と[l,r)が交差している場合
			return Zero1;
 
		if (l <= a && b <= r) { // [l,r)が[a,b)を完全に含んでいる場合
			return dat[k].sum;
		}
 
		int m = (a + b) / 2;
		Value1 vl = get(l, r, 2 * k, a, m);
		Value1 vr = get(l, r, 2 * k + 1, m, b);
		update_node(k);
		return connect(vl, vr);
	}
};


int main() {
	ios::sync_with_stdio(false);
	cin.tie();
    int N;cin>>N;
    vector<Value1>as(N);
    for(int i=0;i<N;++i){
        ll a;cin>>a;
        as[i]=make_pair(a,a*a);
    }
    lazy_segtree seg(N,as);
    int Q;cin>>Q;
    while(Q--){
        int tp;cin>>tp;
        if(tp==1){
            int l,r,a;cin>>l>>r>>a;
            l--;
            seg.update(l,r,a);
        }else{
            int l,r;cin>>l>>r;l--;
            Value1 answer=seg.get(l,r);
            cout<<answer.second<<endl;
        }
    }
	return 0;
}
0