【题解】「JOISC 2021 Day1」饮食区

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{ //(p,q) 表示区间里的数 +p 后对 q 取 max //合并标记要注意先后顺序 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++) { //对于询问操作,判断是否到达 k 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() { // freopen("data.in","r",stdin); 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__

本文作者仰望星空的蚂蚁
本文链接https://www.cnblogs.com/cqbzly/p/17530255.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   仰望星空的蚂蚁  阅读(23)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
点击右上角即可分享
微信分享提示