結果
| 問題 |
No.1234 典型RMQ
|
| コンテスト | |
| ユーザー |
poohbear
|
| 提出日時 | 2020-09-18 22:11:04 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 325 ms / 2,000 ms |
| コード長 | 4,607 bytes |
| コンパイル時間 | 1,876 ms |
| コンパイル使用メモリ | 204,732 KB |
| 最終ジャッジ日時 | 2025-01-14 17:16:37 |
|
ジャッジサーバーID (参考情報) |
judge5 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 27 |
ソースコード
#include <bits/stdc++.h>
#define rep(a,n) for (ll a = 0; a < (n); ++a)
using namespace std;
using ll = long long;
typedef pair<ll,ll> P;
typedef pair<P,ll> PP;
typedef vector<vector<ll> > Graph;
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }
const ll INF = 1e18;
template<typename T,typename M>
struct SegTree{
using FX = function<T(T,T)>;//T●T->Tとなる関数の型
using FA = function<T(T,M)>;
using FM = function<M(M,M)>;
using FP = function<M(M,ll)>;
ll n;
FX fx;
FA fa;
FM fm;
FP fp;
const T ex;//単位元
const M em;
vector<T> node;
vector<M> lazy;
SegTree(ll n_, FX fx_, FA fa_,FM fm_, FP fp_ ,T ex_,M em_)
: n(),fx(fx_),fa(fa_),fm(fm_),fp(fp_),ex(ex_),em(em_),node(n_*4,ex),lazy(n_*4,em){
ll x = 1;
while(n_>x)x*=2;
n=x;
}
void set(ll i,T x){
node[i+n-1] = x;
}
void build(){
for(ll k=n-2;k>=0;k--)node[k]=fx(node[2*k+1],node[2*k+2]);
}
void eval(ll k,ll len){
if(lazy[k]==em)return;//更新がなければ終了
if(k<n-1){//葉でなければ子に伝搬
lazy[k*2+1]=fm(lazy[k*2+1],lazy[k]);
lazy[k*2+2]=fm(lazy[k*2+2],lazy[k]);
}
//自身の更新
node[k]=fa(node[k],fp(lazy[k],len));
lazy[k]=em;
}
void update(ll a, ll b, M x, ll k, ll l, ll r){
eval(k,r-l);
if(a<=l&&r<=b){ //完全に内側
lazy[k]=fm(lazy[k],x);
eval(k,r-l);
}
else if(a<r && l<b){ //一部区間がかぶる
update(a,b,x,k*2+1,l,(l+r)/2);
update(a,b,x,k*2+2,(l+r)/2,r);
node[k]=fx(node[k*2+1],node[k*2+2]);
}
}
void update(ll a,ll b,M x){
update(a,b,x,0,0,n);
}
T query_sub(ll a,ll b,ll k,ll l,ll r){
eval(k,r-l);
if(r<=a || b<=l){
return ex;
}
else if(a<=l && r<=b){
return node[k];
}
else{
T vl = query_sub(a,b,k*2+1,l,(l+r)/2);
T vr = query_sub(a,b,k*2+2,(l+r)/2,r);
return fx(vl,vr);
}
}
T query(ll a,ll b){
return query_sub(a,b,0,0,n);
}
T operator[](ll i){
return query(i,i+1);
}
void print(){//デバッグ用
for(ll i=0;i<n;i++){
cout << (*this)[i];
if(i != n-1)cout << ',';
}
cout << endl;
}
//二分探索で[a,b)でx以下の値を持つ最右の要素位置を見つける
//コメントアウトするとx以上にもできる
//全てx以下なら-1を返す
//後々抽象化出来たらいいな
ll find_right(ll a,ll b,ll x,ll k,ll l,ll r){
eval(k,r-l);
if(node[k]>x||r<=a||b<=l)return -1;
//if(node[k]<x||r<=a||b<=l)return -1;
if(k>=n-1)return (k-(n-1));
ll rv = find_right(a,b,x,2*k+2,(l+r)/2,r);
if(rv!=-1)return rv;
return find_right(a,b,x,2*k+1,l,(l+r)/2);
}
ll find_right(ll a,ll b,ll x){
return find_right(a,b,x,0,0,n);
}
//二分探索で[a,b)でx以下の値を持つ最左の要素位置を見つける
//コメントアウトするとx以上にもできる
//全てx以下なら-1を返す
ll find_left(ll a,ll b,ll x,ll k,ll l,ll r){
eval(k,r-l);
if(node[k]>x||r<=a||b<=l)return -1;
//if(node[k]<x||r<=a||b<=l)return -1;
if(k>=n-1)return (k-(n-1));
ll lv = find_left(a,b,x,2*k+1,l,(l+r)/2);
if(lv!=-1)return lv;
return find_left(a,b,x,2*k+2,(l+r)/2,r);
}
ll find_left(ll a,ll b,ll x){
return find_left(a,b,x,0,0,n);
}
};
int main(){
ll n;
cin >> n;
vector<ll>a(n);
rep(i,n)cin>>a[i];
ll q;
cin >> q;
using X = long long;
using M = long long;
auto fx = [](X x1, X x2) -> X { return min(x1,x2); };
auto fa = [](X x, M m) -> X { return x + m; };
auto fm = [](M m1, M m2) -> M { return m1+m2; };
auto fp = [](M m, long long t) -> M { return m; };
long long ex = numeric_limits<ll>::max();
long long em = 0;
SegTree<X, M> seg(n, fx, fa, fm, fp, ex, em);
rep(i,n){
seg.set(i,a[i]);
}
seg.build();
rep(i,q){
ll k,l,r,c;
cin >> k >> l >> r >> c;
l--;r--;
if(k==1){
seg.update(l,r+1,c);
}
else{
cout << seg.query(l,r+1) << endl;
}
}
return 0;
}
poohbear