转化,值域区间加减
不多赘述了,直接搜索题面即可。
一个很感性的理解就是:初始分数越高,最后的分数也会越高(至少不会更低)
这个特性是因为,每次得分最多也就能 。先不论这道题,来看一个很基础的数学模型。
有一个 若干个数组成的数组 ,其中每个元素都有一个对应的 。我们对其中的元素进行任意次操作,每一次取出值在 的元素,并进行 ,那么操作完成之后每个元素对应的 实际上是不会发生改变的(容易理解)。
这其实在 左右的场次(记不太清了)出过一道 题,同样的背景,只询问操作之后的最值,那么只用关注单点即可。
回到这道题上来,我们定义 为 起始分数为 ,最后能得到的对应分数 ,首先 本身是单调增加的,我们会进行若干次对 中的数 的操作,但是无论进行多少次,这个数组本身一定会保持单调不降(前面已经说明过了)。
所以对于每一次操作,我们二分一下就可以得知操作的左右端点在哪里,然后套一个数据结构就可以 通过了。
但是这并不是最优秀的复杂度,线段树二分可以做到 ,然而我还没学,这里挖个坑。。。
| |
| |
| #include<bits/stdc++.h> |
| using namespace std; |
| const int N=5e5+10; |
| struct SegmentTree |
| { |
| int l,r,val,tag; |
| #define L tr[x].l |
| #define R tr[x].r |
| }tr[N<<2]; |
| inline int calc(int x){return tr[x].val+(tr[x].r-tr[x].l+1)*tr[x].tag;} |
| inline void pd(int x){tr[x<<1].tag+=tr[x].tag,tr[x<<1|1].tag+=tr[x].tag,tr[x].tag=0;} |
| inline void pu(int x){tr[x].val=calc(x<<1)+calc(x<<1|1);} |
| inline void build(int x,int l,int r) |
| { |
| tr[x].l=l,tr[x].r=r; |
| if(l==r) |
| { |
| tr[x].val=l; |
| return ; |
| } |
| int mid=l+r>>1; |
| build(x<<1,l,mid),build(x<<1|1,mid+1,r); |
| pu(x); |
| } |
| inline void modify(int x,int l,int r,int v) |
| { |
| if(l<=L&&R<=r) |
| { |
| tr[x].tag+=v; |
| return ; |
| } |
| pd(x); |
| int mid=L+R>>1; |
| if(l<=mid)modify(x<<1,l,r,v); |
| if(r>mid)modify(x<<1|1,l,r,v); |
| pu(x); |
| } |
| inline int query(int x,int l,int r) |
| { |
| if(l<=L&&R<=r)return calc(x); |
| pd(x); |
| int ans=0; |
| int mid=L+R>>1; |
| if(l<=mid)ans+=query(x<<1,l,r); |
| if(r>mid)ans+=query(x<<1|1,l,r); |
| pu(x); |
| return ans; |
| } |
| struct Query |
| { |
| int l,r; |
| }q[N]; |
| int n,m; |
| int main() |
| { |
| ios::sync_with_stdio(0); |
| cin.tie(0),cout.tie(0); |
| cin>>n; |
| build(1,1,N); |
| for(int i=1;i<=n;++i) |
| { |
| cin>>q[i].l>>q[i].r; |
| int ml,mr; |
| int l=1,r=N; |
| while(l<r) |
| { |
| int mid=l+r>>1; |
| if(query(1,mid,mid)<q[i].l)l=mid+1; |
| else r=mid; |
| } |
| ml=l; |
| l=1,r=N; |
| while(l<r) |
| { |
| int mid=(l+r+1)>>1; |
| if(query(1,mid,mid)>q[i].r)r=mid-1; |
| else l=mid; |
| } |
| mr=l; |
| modify(1,ml,mr,1); |
| } |
| cin>>m; |
| int x; |
| while(m--) |
| { |
| cin>>x; |
| cout<<query(1,x,x)<<'\n'; |
| } |
| return 0; |
| } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
· 凌晨三点救火实录:Java内存泄漏的七个神坑,你至少踩过三个!