CodeForces 992E (势能线段树)

https://codeforces.com/problemset/problem/992/E
题意: 单点修改,询问整个数列中满足 \(a_{i} = s_{i-1}\) 的任意一个i (si是i的前缀和)
思路:

  • 要满足\(a_{i} = s_{i-1}\),必有\(s_{i} = s_{i-1} * 2\),所有最多有log sn个位置满足
  • 线段树维护\(a_{i} - s_{i-1}\), 线段树上询问最大值大于0的区间,找到值等于0的位置
  • 时间复杂度 \(nlogn^2\)
#include<bits/stdc++.h>
//#include <bits/extc++.h>
using namespace std;
// using namespace __gnu_cxx;
// using namespace __gnu_pbds;
#define IOS ios::sync_with_stdio(false) ,cin.tie(0), cout.tie(0);  
//#pragma GCC optimize(3,"Ofast","inline")
#define ll long long
#define ull unsigned long long
#define li __int128_t
#define PII pair<int, int>
#define re register
//#define int long long
const int N = 2e5 + 5;
const int M = 1e6 + 5;
const int mod = 998244353;
const ll LNF = 0x3f3f3f3f3f3f3f3f;
const double PI = acos(-1.0);
inline int read(){
   int s=0,w=1;
   char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
   while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
   return s*w;
}
ll a[N], s[N]; int n; int ans = -1;
struct Tree {
 ll mx, lazy;
}tree[N << 2];
inline void pushup( int rt ) {
 tree[rt].mx = max( tree[rt << 1].mx, tree[rt << 1 | 1].mx );
}
inline void pushdown( int l, int r, int rt ) {
 if( !tree[rt].lazy ) return;
 tree[ rt << 1 ].lazy += tree[rt].lazy;
 tree[ rt << 1 | 1 ].lazy += tree[rt].lazy;
 tree[ rt << 1 ].mx += tree[rt].lazy;
 tree[ rt << 1 | 1 ].mx += tree[rt].lazy;
 tree[rt].lazy = 0;
}
inline void build( int l, int r, int rt ) {
 if( l == r ) {
   tree[rt].mx = a[l] - s[l - 1];
   return;
 }
 int mid = l + r >> 1;
 build( l, mid, rt << 1 ); build( mid + 1, r, rt << 1 | 1 );
 pushup(rt);
}
inline void modify( int a, int b, ll c, int l, int r, int rt ) {
 if( l > b || r < a ) return ;
 if( l >= a && r <= b ) {
   tree[rt].mx += c; tree[rt].lazy += c;
   return;
 }
 pushdown( l, r, rt );
 int mid = l + r >> 1;
 modify( a, b, c, l, mid, rt << 1 );
 modify( a, b, c, mid + 1, r, rt << 1 | 1 );
 pushup(rt);
}
inline void query( int l, int r , int rt) {
 if( ans != -1 ) return;
 if( l == r ) {
   if( !tree[rt].mx ) ans = l;
   return;
 }
 pushdown( l, r, rt );
 int mid = l + r >> 1;
 if( tree[rt << 1].mx >= 0 ) query( l, mid, rt << 1 );
 if( tree[rt << 1 | 1].mx >= 0 ) query( mid + 1, r, rt << 1 | 1 );
}
int main() {

 int q; n = read(), q = read();
 for ( re int i = 1; i <= n; ++ i ) a[i] = read(), s[i] = s[i - 1] + a[i];
 build( 1, n, 1 );
 while ( q --) {
   ll pos, val; pos = read(), val = read();
   val -= a[pos];
   modify( pos, pos, val, 1, n, 1 );
   if ( pos < n ) modify( pos + 1, n, -val, 1, n, 1 );
   a[pos] += val;
   query( 1, n, 1 );
   printf("%d\n", ans);
   ans = -1;
 }
 return 0;
}
posted @ 2022-06-05 10:28  qingyanng  阅读(35)  评论(0编辑  收藏  举报