UOJ #660. 【IOI2021】candies
题面传送门
对着这个题做好像不太好做,考虑到只有一次询问且在最后,我们可以尝试离线。
将修改离线后差分,对每个糖果盒子扫描线,记录\(m\)个不同时间这个糖果盒子的糖果数量。
可以发现,如果一段区间极差大于\(c_i\),那么这段区间最后一定是没有或者满的。
那么我们可以用线段树上二分找到最后面的这样一段区间,然后这段区间后相当于直接加。
但是如果没有这样一个区间的话,那么显然一定没有大于等于\(c_i\)的时候但是会有小于\(0\)的时候,这时我们可以找到最小值,那么这个最小值一定是\(\leq 0\)的。这个最小值后一定没有任何碰顶或碰低。然后直接计算即可。
时间复杂度\(O((n+q)logn)\)
code:
#include "candies.h"
#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define RI re int
#define ll long long
#define db double
#define lb long db
#define N 200000
#define M 500000
#define mod 998244353
#define Mod (mod-1)
#define eps (1e-5)
#define U unsigned int
#define it iterator
#define Gc() getchar()
#define Me(x,y) memset(x,y,sizeof(x))
#define d(x,y) (m*x+(y))
#define R(n) (rand()*rand()%(n)+1)
#define Pc(x) putchar(x)
#define LB lower_bound
#define UB upper_bound
using namespace std;
int n,m;const ll INF=1e18;vector<int> Ans;
struct Ques{int T,w;};vector<Ques> S[N+5];
namespace Tree{
#define ls now<<1
#define rs now<<1|1
ll Ma[N+5<<2],Mi[N+5<<2],F[N+5<<2];I void Up(int now){Ma[now]=max(Ma[ls],Ma[rs]);Mi[now]=min(Mi[ls],Mi[rs]);}
I void PF(int x,ll w){F[x]+=w;Ma[x]+=w;Mi[x]+=w;}I void P(int now){F[now]&&(PF(ls,F[now]),PF(rs,F[now]),F[now]=0);}
I void Ins(int x,int y,int w,int l=0,int r=m,int now=1){if(x<=l&&r<=y)return PF(now,w);int m=l+r>>1;P(now);x<=m&&(Ins(x,y,w,l,m,ls),0);y>m&&(Ins(x,y,w,m+1,r,rs),0);Up(now);}
I ll Qry(int x,int l=0,int r=m,int now=1){if(l==r) return Ma[now];int m=l+r>>1;P(now);return x<=m?Qry(x,l,m,ls):Qry(x,m+1,r,rs);}
I ll Find(int x,ll L,ll R,int l=0,int r=m,int now=1){if(l==r) return L=min(L,Mi[now]),R=max(R,Mi[now]),/*printf("%d %d %lld %lld\n",x,l,L,R),*/R-L>=x?(L^Mi[now]?Qry(m)-L:x+Qry(m)-R):(Qry(m)-Mi[1]);int m=l+r>>1;P(now);return max(R,Ma[rs])-min(L,Mi[rs])>=x?Find(x,L,R,m+1,r,rs):Find(x,min(L,Mi[rs]),max(R,Ma[rs]),l,m,ls);}
#undef ls
#undef rs
}
std::vector<int> distribute_candies(vector<int> c,vector<int> l,vector<int> r,vector<int> v) {
RI i,j;n=c.size();m=l.size();for(i=0;i<m;i++) S[l[i]].push_back((Ques){i+1,v[i]}),S[r[i]+1].push_back((Ques){i+1,-v[i]});
for(i=0;i<n;i++) {for(j=0;j<S[i].size();j++) Tree::Ins(S[i][j].T,m,S[i][j].w);Ans.push_back(Tree::Find(c[i],INF,-INF));}return Ans;
}