結果
問題 | 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 |
ソースコード
#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; }