首页 > 代码库 > hdu4417 线段树+离线处理
hdu4417 线段树+离线处理
题意是给你一个序列 m次询问 每次询问区间内比给定值小的有多少个
首先相到的肯定是线段树 但是按常规的做不容易做出来 这里用到离线处理 及先把所有的询问区间输入存起来并保存原来id 进行如下处理
对每段区间按高度从小到大排序 把序列也按从小到大排序并保存原来id
i表示插入位置 j表示询问位置 如果当前i表示的高度比当前j表示的高度小则跟新 否则查询(这样子的原因是当查询当前j表示的高度时只用跟上比他小的高度 )具体见代码
#include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> using namespace std; #define LL(x) (x<<1) #define RR(x) ((x<<1)|1) struct node { int high; int ii; }A[100100]; struct Node { int L,R,h,i; }f[100100]; int cmp1(node a,node b) { return a.high<b.high; } int cmp2(Node a,Node b) { return a.h<b.h; } int num[4*100000]; int update(int L,int R,int pos,int mark) { num[mark]+=1; if(L==R&&L==pos) { return 0; } int mid=(L+R)/2; if(pos<=mid) { update(L,mid,pos,LL(mark)); } else update(mid+1,R,pos,RR(mark)); return 0; } int find(int L,int R,int left,int right,int mark) { if(L==left&&R==right) { return num[mark]; } int mid=(L+R)/2; if(right<=mid) { return find(L,mid,left,right,LL(mark)); } else if(left>mid) { return find(mid+1,R,left,right,RR(mark)); } else return find(L,mid,left,mid,LL(mark))+find(mid+1,R,mid+1,right,RR(mark)); } int main() { int n,m,i,j,a,T,b,c,d=1; int print[100010]; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); for(i=1;i<=n;i++) { scanf("%d",&A[i].high); A[i].ii=i; } for(i=1;i<=m;i++) { scanf("%d%d%d",&f[i].L,&f[i].R,&f[i].h); f[i].L++; f[i].R++; f[i].i=i; } sort(A+1,A+1+n,cmp1); sort(f+1,f+1+m,cmp2); memset(num,0,sizeof(num)); int j=1; for(i=1;i<=n;) { if(A[i].high>f[j].h) { print[f[j].i]=find(1,n,f[j].L,f[j].R,1); j++; if(j>m) break; } if(A[i].high<=f[j].h) { update(1,n,A[i].ii,1); i++; } } while(j<=m) { print[f[j].i]=find(1,n,f[j].L,f[j].R,1); j++; } printf("Case %d:\n",d++); for(i=1;i<=m;i++) printf("%d\n",print[i]); } return 0; }
hdu4417 线段树+离线处理
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。