【BZOJ2221】面试的考验,随机数列+线段树+离线
来源:互联网 发布:holi天气数据来源 编辑:程序博客网 时间:2024/05/17 06:09
传送门
shallwe’s blog //以上内容由shallwe本人暴力添加
思路:
好题
断断续续想了1周左右
暴力思路显然是
我最开始的想法是用莫队+set来搞
但是发现即使是在随机数列下,
那怎么办?
(下列做法可能比较难想……)
如果说我们处理出当前区间中每个元素往前的最小差值,那不就可以得到答案了吗?
再深入思考一下
对于
对于这道题来说,这个性质是极好的
这样就相当于每次找某个权值区间中位置小于某个值的最大位置了
但这样并不好找
因为当前点后面的数会对我们查询产生影响
那就从左向右扫着做,后面数就不会有影响了
这样就相当于找某个权值区间中的最大位置了
这就很好办了啊
权值线段树就可以了
操作是单点修改和区间求max
那每次求出的答案的贡献区间是什么呢?
如果说当前点为r,找到的贡献点是l,那么它对答案的贡献区间是左端点在
这不是很好维护
所以我们干脆把询问离线下来,以右端点为关键字从小到大排序,然后把所有的答案都记到左端点上,这样就可以拿一颗新的线段树来维护了
每次修改的区间就是
操作是区间修改和区间求min
总结一下就是随机数列的神奇性质+离线+扫描线思想+双线段树维护
代码还是挺好写的 题解好难写啊
代码:
#include<cstdio>#include<iostream>#include<algorithm>#define M 100005#define up 2147483647using namespace std;int n,m;int a[M],b[M],ha[M],S[M<<2],V[M<<2],lazy[M<<2],ans[M];struct query{ int id,l,r;}q[M];int in(){ int t=0;char ch=getchar();bool f=0; while (ch>'9'||ch<'0') f=(ch=='-'),ch=getchar(); while (ch>='0'&&ch<='9') t=(t<<1)+(t<<3)+ch-48,ch=getchar(); return f?-t:t;}bool cmp(query a,query b){ return a.r<b.r;}int V_get(int rt,int begin,int end,int l,int r){ if (l<=begin&&end<=r) return V[rt]; int mid=begin+end>>1,ans=0; if (mid>=l) ans=max(ans,V_get(rt<<1,begin,mid,l,r)); if (mid<r) ans=max(ans,V_get(rt<<1|1,mid+1,end,l,r)); return ans;}void V_update(int rt,int begin,int end,int pos,int val){ if (begin==end) return void(V[rt]=val); int mid=begin+end>>1; if (mid>=pos) V_update(rt<<1,begin,mid,pos,val); else V_update(rt<<1|1,mid+1,end,pos,val); V[rt]=val;}void S_build(int rt,int begin,int end){ S[rt]=up; if (begin==end) return; int mid=begin+end>>1; S_build(rt<<1,begin,mid); S_build(rt<<1|1,mid+1,end);}void pushdown(int rt){ if (!lazy[rt]) return; S[rt<<1]=min(S[rt<<1],lazy[rt]); if (!lazy[rt<<1]) lazy[rt<<1]=lazy[rt]; else lazy[rt<<1]=min(lazy[rt],lazy[rt<<1]); S[rt<<1|1]=min(S[rt<<1|1],lazy[rt]); if (!lazy[rt<<1|1]) lazy[rt<<1|1]=lazy[rt]; else lazy[rt<<1|1]=min(lazy[rt],lazy[rt<<1|1]); lazy[rt]=0;}void S_update(int rt,int begin,int end,int l,int r,int val){ if (l<=begin&&end<=r) { S[rt]=min(S[rt],val); if (!lazy[rt]) lazy[rt]=val; else lazy[rt]=min(val,lazy[rt]); return; } pushdown(rt); int mid=begin+end>>1; if (mid>=l) S_update(rt<<1,begin,mid,l,r,val); if (mid<r) S_update(rt<<1|1,mid+1,end,l,r,val); S[rt]=min(S[rt<<1],S[rt<<1|1]);}int S_get(int rt,int begin,int end,int l,int r){ if (l<=begin&&end<=r) return S[rt]; pushdown(rt); int mid=begin+end>>1,ans=up; if (mid>=l) ans=min(ans,S_get(rt<<1,begin,mid,l,r)); if (mid<r) ans=min(ans,S_get(rt<<1|1,mid+1,end,l,r)); return ans;}void cal(int x){ int y=1,val=b[0],ans=up; for (;val>a[x]&&y;) { y=V_get(1,1,b[0],a[x],val); if (y&&a[y]!=a[x]) ans=min(ans,ha[a[y]]-ha[a[x]]), S_update(1,1,n,1,y,ha[a[y]]-ha[a[x]]); if (!y) break; val=a[y]-1; } val=1;y=1; for (;val<a[x]&&y;) { y=V_get(1,1,b[0],val,a[x]); if (y&&a[y]!=a[x]) ans=min(ans,ha[a[x]]-ha[a[y]]), S_update(1,1,n,1,y,ha[a[x]]-ha[a[y]]); if (!y) break; val=a[y]+1; } V_update(1,1,b[0],a[x],x);}main(){ n=in();m=in(); for (int i=1;i<=n;++i) b[i]=a[i]=in(); sort(b+1,b+n+1); b[0]=unique(b+1,b+n+1)-b-1; for (int i=1;i<=b[0];++i) ha[i]=b[i]; for (int i=1;i<=n;++i) a[i]=lower_bound(b+1,b+b[0]+1,a[i])-b; for (int i=1;i<=m;++i) q[i]=(query){i,in(),in()}; sort(q+1,q+m+1,cmp); int last=0; S_build(1,1,n); for (int i=1;i<=m;++i) { for (int j=last+1;j<=q[i].r;++j) cal(j); ans[q[i].id]=S_get(1,1,n,q[i].l,q[i].r); last=q[i].r; } for (int i=1;i<=m;++i) printf("%d\n",ans[i]);}
0 0
- 【BZOJ2221】面试的考验,随机数列+线段树+离线
- BZOJ2221——[Jsoi2009]面试的考验&&codeforces765F——Souvenirs
- [扫描线 树状数组 随机数列 优化] BZOJ 2221 [Jsoi2009]面试的考验
- 面试中成长(大学毕业面临的考验)
- [JSOI2009]面试的考验 解题报告
- 斐波纳契数列 线段树的维护
- 【bzoj4636】【蒟蒻的数列】【线段树】
- 线段树-洛谷P1438 无聊的数列
- zoj3800线段树+离线
- 线段树--数列操作
- 产生随机数列的函数
- hdu4638(离线算法+线段树)
- hdu3874(离线思想+线段树)
- zoj 3724 离线+线段树
- HDU 4417 离线线段树
- HDU 3333 离线线段树
- POJ 2761 离线线段树
- 线段树离线处理专题
- thinkphp学习笔记
- 可拖拽移位,可删除的listview功能 recyclerView
- 浏览器如何访问最新js文件
- //选择完下拉框后加载数据
- 配置vim+NERDTree+ Source Explorer+ Tag List
- 【BZOJ2221】面试的考验,随机数列+线段树+离线
- leetcode解题报告:56. Merge Intervals
- K 聚类分析实现类源码
- 单例的智能指针实现
- 项目中友盟推送适配iOS10
- 使用Spring Boot快速构建应用
- SQL Server复制系列1 – 事务复制中的snapshot
- angularjs学习心得
- html php 重定向 跳转 刷新