ZOO
2016-02-25 18:32
423 查看
题目大意
M个询问询问区间K小值。整体二分
我们用K大数查询这道题的思路整体二分。这道题直接套用K大数查询需要带两个log。
我们把询问l~r拆为两个询问1~r和1~l-1,那么每个询问都变成一个前缀,于是我们想着搞一波线性作法。
观察到对于答案区间为l~r,我们只需要扫描在这个区间内的数。
也就是说对于l~r中的数,<=mid的数继续归到左区间其余归到右区间。
一个区间内的询问按照右端点排序,然后就可以线性做。
总复杂度n log n。
注意本题答案范围比较大故先进行离散化。
#include<cstdio> #include<algorithm> #define fo(i,a,b) for(i=a;i<=b;i++) #define fd(i,a,b) for(i=a;i>=b;i--) using namespace std; const int maxn=100000+10; struct dong{ int a,cnt,x; bool p; }; dong ask[maxn*2]; int h1[maxn*5],h2[maxn*5],h3[maxn*5],la1[maxn*5],la2[maxn*5],la3[maxn*5],n1[maxn*20],n2[maxn*20],n3[maxn*20],g1[maxn*20],g2[maxn*20],g3[maxn*20]; int a[maxn],h[maxn],ans[maxn],rank[maxn],id[maxn*2]; int i,j,k,l,t,n,m,t1,t2,t3; //h1=dl h2=ld h3=que void add1(int x,int y){ g1[++t1]=y; n1[la1[x]]=t1; la1[x]=t1; if (!h1[x]) h1[x]=t1; } void add2(int x,int y){ g2[++t2]=y; n2[la2[x]]=t2; la2[x]=t2; if (!h2[x]) h2[x]=t2; } void add3(int x,int y){ g3[++t3]=y; n3[la3[x]]=t3; la3[x]=t3; if (!h3[x]) h3[x]=t3; } void solve(int p,int l,int r){ int j,i,k,t,num=0; if (l==r){ t=h3[p]; while (t){ j=g3[t]; ans[j]=h[l]; t=n3[t]; } return; } int mid=(l+r+1)/2; i=h2[p];k=h1[p]; while (i){ t=g2[i]; while (k){ j=g1[k]; if (ask[j].a>=t) break; ask[j].x=num; k=n1[k]; } if (a[t]<=mid-1) num++; i=n2[i]; } while (k){ j=g1[k]; ask[j].x=num; k=n1[k]; } i=h3[p]; while (i){ t=g3[i]; if (ask[t*2].cnt+ask[t*2].x-ask[t*2-1].cnt-ask[t*2-1].x<=rank[t]-1){ ask[t*2].cnt+=ask[t*2].x; ask[t*2-1].cnt+=ask[t*2-1].x; ask[t*2].x=ask[t*2-1].x=0; ask[t*2-1].p=ask[t*2].p=1; add3(p*2+1,t); } else{ ask[t*2].x=ask[t*2-1].x=0; ask[t*2-1].p=ask[t*2].p=0; add3(p*2,t); } i=n3[i]; } i=h1[p]; while (i){ t=g1[i]; if (ask[t].p) add1(p*2+1,t);else add1(p*2,t); i=n1[i]; } i=h2[p]; while (i){ t=g2[i]; if (a[t]<=mid-1) add2(p*2,t);else add2(p*2+1,t); i=n2[i]; } solve(p*2,l,mid-1); solve(p*2+1,mid,r); } bool cmp(int a,int b){ return ask[a].a<ask[b].a; } int main(){ scanf("%d%d",&n,&m); fo(i,1,n){ scanf("%d",&a[i]); h[i]=a[i]; } sort(h+1,h+n+1); fo(i,1,n) a[i]=lower_bound(h+1,h+n+1,a[i])-h,add2(1,i); fo(i,1,m){ scanf("%d%d%d",&j,&k,&l); rank[i]=l; add3(1,i); ask[i*2-1].a=j-1; ask[i*2].a=k; } fo(i,1,m*2) id[i]=i; sort(id+1,id+m*2+1,cmp); fo(i,1,m*2) add1(1,id[i]); solve(1,1,n); fo(i,1,m) printf("%d\n",ans[i]); }
相关文章推荐
- mysql优化(2)索引优化 配置优化
- #ifndef/#define/#endif以及#if defined/#else/#endif使用详解
- hadoop2.2.0集群的高可用HA及MapReduce简单配置
- delphi与汇编
- IOS开发之----NSDictionary,JSON和XML互相转换
- UITableView
- java,在路上
- Android 5.1 Lollipop的Zygote分析——下篇
- mysql优化(1)show命令 慢查询日志 explain profiling
- Maven3.3.3安装部署教程
- 高通平台手机开发之Sensor
- 服务程序增加系统托盘
- Android 5.1 Lollipop的Zygote分析——上篇
- 用内存流 文件流 资源生成客户端(Delphi开源)
- 把war包放到Tomcat安装文件夹下,不能直接訪问的解决方式
- 【SPOJ-PT07Z】Longest path in a tree【DFS/BFS】【树的直径】
- 在github上贡献自己的资源(issue, pull request 操作)步骤
- UiAutomator注入和查找事件源码浅析
- linux:chmod详解
- QQ聊天界面