結果
問題 | No.619 CardShuffle |
ユーザー |
|
提出日時 | 2018-01-14 21:07:34 |
言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 908 ms / 3,000 ms |
コード長 | 4,150 bytes |
コンパイル時間 | 1,413 ms |
コンパイル使用メモリ | 115,844 KB |
実行使用メモリ | 13,696 KB |
最終ジャッジ日時 | 2024-12-24 03:10:19 |
合計ジャッジ時間 | 17,308 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge1 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 1 |
other | AC * 35 |
ソースコード
#define _USE_MATH_DEFINES#include <cstdio>#include <iostream>#include <sstream>#include <fstream>#include <iomanip>#include <algorithm>#include <cmath>#include <complex>#include <string>#include <vector>#include <list>#include <queue>#include <stack>#include <set>#include <map>#include <bitset>#include <numeric>#include <limits>#include <climits>#include <cfloat>#include <functional>#include <iterator>using namespace std;const int MOD = 1000000007;class SegmentTree{public:typedef pair<char, vector<long long> > T1;typedef pair<char, vector<long long> > T2;// データの初期値、以下の条件を満たすこと// uniteData(v, INIT_DATA) == vstatic const T1 INIT_DATA;private:// 前回の値がprevである要素に対して、// パラメータxを用いた更新処理を適用した後の計算結果を返すT1 updateData(T1 prev, T2 x){return x;}// 2つの区間の計算結果v1,v2に対して、// その2つの区間を統合した区間における計算結果を返すT1 uniteData(T1 v1, T1 v2){if(v1.first == '\0')return v2;if(v2.first == '\0')return v1;auto a = v1.second;const auto& b = v2.second;unsigned i = 0;if(v2.first == '*'){a.back() *= b[0];a.back() %= MOD;++ i;}for(; i<b.size(); ++i){if(a.size() == 3){a[1] += a[2];a[1] %= MOD;a.resize(2);}a.push_back(b[i]);}return make_pair(v1.first, a);}int n;vector<T1> data;void updateTree(int a, int k, int l, int r, T2 x){if(a == l && a == r){data[k] = updateData(data[k], x);}else if(l <= a && a <= r){updateTree(a, k*2+1, l, (l+r)/2, x);updateTree(a, k*2+2, (l+r+1)/2, r, x);data[k] = uniteData(data[k*2+1], data[k*2+2]);}}T1 getValue(int a, int b, int k, int l, int r){if(a <= l && r <= b){return data[k];}else if(a <= r && l <= b){T1 v1 = getValue(a, b, k*2+1, l, (l+r)/2);T1 v2 = getValue(a, b, k*2+2, (l+r+1)/2, r);return uniteData(v1, v2);}else{return INIT_DATA;}}public:SegmentTree(int n0){n = 1;while(n < n0)n *= 2;data.assign(2*n-1, INIT_DATA);}SegmentTree(const vector<T1>& v) : SegmentTree((int)v.size()){for(unsigned i=0; i<v.size(); ++i)data[n-1+i] = v[i];for(int k=n-2; k>=0; --k)data[k] = uniteData(data[k*2+1], data[k*2+2]);}// a番目の要素にパラメータxによる更新処理を適用void update(int a, T2 x){updateTree(a, 0, 0, n-1, x);}// 区間[a,b]の計算結果を返すT1 get(int a, int b){return getValue(a, b, 0, 0, n-1);}T1 get(int a, int b, T1 leftPrev, T1 rightPrev){return uniteData(uniteData(leftPrev, get(a, b)), rightPrev);}};const SegmentTree::T1 SegmentTree::INIT_DATA('\0', {});int main(){int n;cin >> n;vector<pair<char, vector<long long> > > v(n/2+1, make_pair('+', vector<long long>(1)));for(int i=1; i<=n; ++i){if(i % 2 == 0)cin >> v[i/2].first;elsecin >> v[i/2].second[0];}int q;cin >> q;SegmentTree st(v);while(--q >= 0){char t;int x, y;cin >> t >> x >> y;if(t == '!'){if(x % 2 == 0)swap(v[x/2].first, v[y/2].first);elseswap(v[x/2].second, v[y/2].second);st.update(x/2, v[x/2]);st.update(y/2, v[y/2]);}else{auto tmp = st.get(x/2, y/2);long long ans = accumulate(tmp.second.begin(), tmp.second.end(), 0LL);ans %= MOD;cout << ans << endl;}}return 0;}