P14003 [eJOI 2025] Reactions 解题报告
题目意思
随便找的题目,树状数组和离散化,很板子的东西不会细说
给定两个数组 \(D_i,T_i\),求 \(\max\limits_{i=1}^{n}{(\sum\limits_{j=i}^n[\sum\limits_{k=i}^jD_k \ge T_j])}\)。
思路
首先如果你将上面那个式子分解或者稍稍理解一下就能想到将区间加和,区间问题转化为单点问题,即使用前缀和,这样就变成了对于每一个 \(i\) 求有多少个 \(j\) 满足 \(j\ge i,Sum_j-Sum_{i-1}\ge T_j\) 其中 \(Sum\) 是前缀和数组
稍稍移项,变成 \(Sum_j-T_j\ge Sum_{i-1}\),接下来就是很板子的东西了,直接上一个离散化把每个数的这两项离散化掉,然后发现要求 \(j\ge i\),所以从后往前扫,每一次使用树状数组单点加不等式前面的东西,然后树状数组访问后面的东西即可,时间复杂度 \(O(n\log_2n)\)。
代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<climits>
#include<cmath>
#include<vector>
#define ll long long
using namespace std;
const ll M=1e6+9;
ll sum[M],n,la[M],cnt,a[M],b[M];
struct SGT{
#define lowbit(x) (x&(-x))
ll tr[M<<2];
inline void change(ll x){
for(;x<=cnt;x+=lowbit(x))
tr[x]++;
}
inline ll query(ll x){
ll ans=0;
for(;x;x-=lowbit(x))
ans+=tr[x];
return ans;
}
}seg;
ll reactions(int N, std::vector<int> G, std::vector<long long> T);
ll reactions(int N, std::vector<int> G, std::vector<long long> T){
vector<ll> D;
for(int i=0;i<N;i++){
if(i>0) D.push_back(D[i-1]+G[i]);
else D.push_back(G[i]);
}
for(int i=0;i<N;i++){
if(i==0){
la[++cnt]=0;
la[++cnt]=D[i]-T[i];
continue;
}
la[++cnt]=D[i-1];
la[++cnt]=D[i]-T[i];
}
sort(la+1,la+cnt+1);
cnt=unique(la+1,la+cnt+1)-la-1;
for(int i=1;i<N;i++){
//a[i] for query,b[i] for change
a[i]=lower_bound(la+1,la+cnt+1,D[i-1])-la;
b[i]=lower_bound(la+1,la+cnt+1,D[i]-T[i])-la;
}
ll ans=0,pos0=lower_bound(la+1,la+cnt+1,0)-la;
a[0]=pos0;b[0]=lower_bound(la+1,la+cnt+1,D[0]-T[0])-la;
for(int i=N-1;i>=0;i--){
seg.change(cnt-b[i]+1);
if(i!=0)ans=max(ans,seg.query(cnt-a[i]+1));
else ans=max(ans,seg.query(cnt-pos0+1));
}
return ans;
}

浙公网安备 33010602011771号