結果
| 問題 |
No.2861 Slime Party
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2025-10-05 23:32:44 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 372 ms / 4,000 ms |
| コード長 | 5,343 bytes |
| コンパイル時間 | 2,707 ms |
| コンパイル使用メモリ | 205,228 KB |
| 実行使用メモリ | 37,664 KB |
| 最終ジャッジ日時 | 2025-10-05 23:33:17 |
| 合計ジャッジ時間 | 31,713 ms |
|
ジャッジサーバーID (参考情報) |
judge3 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 76 |
ソースコード
// ai benchmark
#include <bits/stdc++.h>
using namespace std;
using int64 = long long;
using i128 = __int128_t;
struct Fenwick {
int n;
vector<long long> bit;
Fenwick() {}
Fenwick(int n): n(n), bit(n+1,0) {}
void add(int idx, long long v){
for(; idx<=n; idx+=idx&-idx) bit[idx]+=v;
}
long long sumPrefix(int idx) const{
long long r=0;
for(; idx>0; idx-=idx&-idx) r+=bit[idx];
return r;
}
long long sumRange(int l, int r) const{
if(r<l) return 0;
return sumPrefix(r)-sumPrefix(l-1);
}
};
struct SegTree {
int n;
vector<long long> mx, lz;
SegTree() {}
SegTree(int n): n(n), mx(4*n+4, LLONG_MIN/4), lz(4*n+4, 0) {}
void build(const vector<long long>& a){ build(1,1,n,a); }
void build(int p, int l, int r, const vector<long long>& a){
if(l==r){ mx[p]=a[l]; return; }
int m=(l+r)>>1;
build(p<<1,l,m,a);
build(p<<1|1,m+1,r,a);
mx[p]=max(mx[p<<1],mx[p<<1|1]);
}
void push(int p){
if(lz[p]!=0){
long long v=lz[p];
lz[p<<1]+=v; mx[p<<1]+=v;
lz[p<<1|1]+=v; mx[p<<1|1]+=v;
lz[p]=0;
}
}
void rangeAdd(int L, int R, long long v){ if(L>R) return; rangeAdd(1,1,n,L,R,v); }
void rangeAdd(int p, int l, int r, int L, int R, long long v){
if(R<l || r<L) return;
if(L<=l && r<=R){ mx[p]+=v; lz[p]+=v; return; }
push(p);
int m=(l+r)>>1;
rangeAdd(p<<1,l,m,L,R,v);
rangeAdd(p<<1|1,m+1,r,L,R,v);
mx[p]=max(mx[p<<1],mx[p<<1|1]);
}
// find the greatest index <= pos with value >= thr; return 0 if none
int find_last_ge(int pos, long long thr){ return find_last_ge(1,1,n,pos,thr); }
int find_last_ge(int p, int l, int r, int pos, long long thr){
if(l>pos) return 0;
if(mx[p] < thr) return 0;
if(l==r) return l;
push(p);
int m=(l+r)>>1;
int res = 0;
if(m<pos){
res = find_last_ge(p<<1|1,m+1,r,pos,thr);
if(res) return res;
return find_last_ge(p<<1,l,m,pos,thr);
}else{
// entire right child is beyond pos
return find_last_ge(p<<1,l,m,pos,thr);
}
}
// find the smallest index >= pos with value >= thr; return n+1 if none
int find_first_ge(int pos, long long thr){ return find_first_ge(1,1,n,pos,thr); }
int find_first_ge(int p, int l, int r, int pos, long long thr){
if(r<pos) return n+1;
if(mx[p] < thr) return n+1;
if(l==r) return l;
push(p);
int m=(l+r)>>1;
int res = find_first_ge(p<<1,l,m,pos,thr);
if(res!=n+1) return res;
return find_first_ge(p<<1|1,m+1,r,pos,thr);
}
};
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int N, Q;
long long L;
if(!(cin>>N>>Q>>L)) return 0;
vector<long long> A(N+1), X(N+1);
for(int i=1;i<=N;i++) cin>>A[i];
for(int i=1;i<=N;i++) cin>>X[i];
// prefix sums of X
Fenwick fw(N);
for(int i=1;i<=N;i++) fw.add(i, X[i]);
// Build base arrays for segtrees:
// V_L[i] = A[i] + P[i]
// V_R[i] = A[i] - P[i-1]
vector<long long> pref(N+1,0);
for(int i=1;i<=N;i++) pref[i]=pref[i-1]+X[i];
vector<long long> VL(N+1), VR(N+1);
for(int i=1;i<=N;i++){
VL[i] = A[i] + pref[i];
VR[i] = A[i] - pref[i-1];
}
SegTree segL(N), segR(N);
segL.build(VL);
segR.build(VR);
auto solve_gap = [&](int k)->long long{
// l = k (last uncleared on left), r = k+1 (first uncleared on right)
int l = k, r = k+1;
long long Pk = fw.sumPrefix(k);
long long TR0 = L + Pk; // L + P[r-1] (initially r-1=k)
long long TL0 = L - Pk; // L - P[l]
// Expand alternately until stable. Each expansion jumps to the current maximal run.
int prev_l = -1, prev_r = -1;
long long SL = 0, SR = 0;
for(;;){
// stop if no movement
if(prev_l==l && prev_r==r) break;
prev_l = l; prev_r = r;
// Expand left with fixed TR = TR0 + SR
long long TR = TR0 + SR;
int blockLeft = segL.find_last_ge(l, TR); // last index <= l with V_L >= TR
// if none, 0
l = (blockLeft<0?0:blockLeft);
SL = fw.sumRange(l+1, k);
// Expand right with fixed TL = TL0 + SL
long long TL = TL0 + SL;
int blockRight = segR.find_first_ge(r, TL); // first index >= r with V_R >= TL
if(blockRight == N+1) r = N+1;
else r = blockRight;
SR = fw.sumRange(k+1, r-1);
}
return L + SL + SR;
};
for(int qi=0; qi<Q; ++qi){
int t; cin>>t;
if(t==1){
int a; long long b; cin>>a>>b;
long long delta = b - X[a];
if(delta!=0){
X[a]=b;
fw.add(a, delta);
// Update V_L[i] += delta for i>=a
segL.rangeAdd(a, N, delta);
// Update V_R[i] -= delta for i>=a+1
if(a+1<=N) segR.rangeAdd(a+1, N, -delta);
}
}else{
int c; cin>>c; // start between c and c+1
cout << solve_gap(c) << '\n';
}
}
return 0;
}