solution:
考虑算法:整体二分 。
考虑没有删除怎么做。因为满足单调性,可以直接二分 使得队列人数第一次
≥
B
i
\geq B_i
≥Bi 时的修改编号 。
加上删除操作后还是有单调性,只不过要 预处理出删除操作对查询的影响 。
这里抛出一个结论:从左往右扫描,删除对当前询问影响=当前加入队列的总人数-当前实际人数。
考虑后面的,本质上就是每次全部元素对 0 取 max ,考虑 区间最值线段树 。
维护懒标
(
p
,
q
)
(p,q)
(p,q) 表示区间里的数 +p 后对 q 取 max ,合并结果大致为:
①
q
=
max
(
q
+
u
,
v
)
q=\max (q+u,v)
q=max(q+u,v)
②
p
=
p
+
u
p=p+u
p=p+u
合并标记时要注意先后顺序。
整个过程完全可以用 线段树+树状数组 维护。满足 区间修改 + 单点查询。
总结:本题考查一些数据结构常见算法。我都没见过。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int Maxn=3e5+5;
int n,m,Q,ans[Maxn],cnt,idx[Maxn],qidx,sidx;
ll bit[Maxn];
inline ll read()
{
ll X=0; bool flag=1; char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-') flag=0; ch=getchar();}
while(ch>='0'&&ch<='9') {X=(X<<1)+(X<<3)+ch-'0'; ch=getchar();}
if(flag) return X;
return ~(X-1);
}
struct node{
int type,l,r,id;
ll k;
}q[Maxn],q1[Maxn],q2[Maxn];
struct SegmentTree{
struct node{
ll p,q;
}t[Maxn<<2];
void PushUp(int p,ll u,ll v) {
t[p].q=max(t[p].q+u,v);
t[p].p+=u;
}
void PushDown(int p) {
if(t[p].p||t[p].q) {
PushUp(p<<1,t[p].p,t[p].q);
PushUp(p<<1|1,t[p].p,t[p].q);
t[p].p=t[p].q=0;
}
}
void upd(int p,int l,int r,int ql,int qr,int k) {
if(ql<=l&&r<=qr) {
PushUp(p,k,0);
return;
}
PushDown(p);
int mid=l+r>>1;
if(ql<=mid) upd(p<<1,l,mid,ql,qr,k);
if(mid<qr) upd(p<<1|1,mid+1,r,ql,qr,k);
}
ll qry(int p,int l,int r,int x) {
if(l==r) return max(t[p].p,t[p].q);
int mid=l+r>>1; PushDown(p);
return x<=mid?qry(p<<1,l,mid,x):qry(p<<1|1,mid+1,r,x);
}
}T1;
void add(int x,int k) {
for(int i=x;i<=n;i+=i&-i) bit[i]+=k;
}
ll qry(int x) {
ll tot=0;
for(int i=x;i;i-=i&-i) tot+=bit[i];
return tot;
}
void solve(int l,int r,int ql,int qr) {
if(l>r||ql>qr) return;
int mid=ql+qr>>1;
int cnt1=0,cnt2=0,cnt3=0,cnt4=0;
for(int i=l;i<=r;i++) {
if(q[i].type==0) {
ll tmp=qry(q[i].l);
if(tmp>=q[i].k) {
q1[++cnt1]=q[i];
cnt3++;
}
else {
q[i].k-=tmp;
q2[++cnt2]=q[i];
cnt4++;
}
}
else {
if(q[i].id<=mid) {
add(q[i].l,q[i].k);
add(q[i].r+1,-q[i].k);
q1[++cnt1]=q[i];
}
else {
q2[++cnt2]=q[i];
}
}
}
for(int i=l;i<=r;i++) {
if(q[i].type==1&&q[i].id<=mid) {
add(q[i].l,-q[i].k);
add(q[i].r+1,q[i].k);
}
}
if(ql==qr) {
for(int i=1;i<=cnt1;i++) {
if(q1[i].type==0) {
ans[q1[i].id]=idx[ql];
}
}
return;
}
for(int i=1;i<=cnt1;i++) {
q[l+i-1]=q1[i];
}
for(int i=1;i<=cnt2;i++) {
q[l+cnt1+i-1]=q2[i];
}
if(cnt3) solve(l,l+cnt1-1,ql,mid);
if(cnt4) solve(l+cnt1,r,mid+1,qr);
}
signed main() {
n=read(),m=read(),Q=read();
for(int i=1;i<=Q;i++) {
int op=read();
if(op==1) {
int l=read(),r=read(),c=read(),k=read();
q[++cnt].type=1;
q[cnt].l=l;
q[cnt].r=r;
q[cnt].k=k;
q[cnt].id=++qidx;
idx[qidx]=c;
add(l,k),add(r+1,-k);
T1.upd(1,1,n,l,r,k);
}
else if(op==2) {
int l=read(),r=read(),k=read();
T1.upd(1,1,n,l,r,-k);
}
else if(op==3) {
int l=read(); ll k=read();
q[++cnt].type=0;
q[cnt].l=l;
q[cnt].k=k+qry(l)-T1.qry(1,1,n,l);
q[cnt].id=++sidx;
}
}
memset(bit,0,sizeof(bit));
solve(1,cnt,1,qidx);
for(int i=1;i<=sidx;i++) {
printf("%lld\n",ans[i]);
}
}
__EOF__
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」