HDU4343Interval query 倍增
来源:互联网 发布:数控编程专业介绍 编辑:程序博客网 时间:2024/06/01 09:30
题意
给定n个区间[a,b),都是左闭右开,有m次询问,每次询问你最多可以从n个区间中选出多少[L,R]的子区间,使得他们互不相交。 n,m<=10^5。 区间下标<=10^9。
题解
这题要用倍增。
首先,给区间按照左端点编号排个序。
如果区间A包含了区间B,那么A一定没用,扔了。
那么剩余的区间[x,y]的x和y一定都是升序的。
之后,就是对于区间的贪心了:
找到一个区间[xi,yi]之后,一定是寻找一个xj>yi且xj最小的那个区间[xj,yj],所以设该区间的编号j=next[i];这个只要二分查找一下就可以了。
那么贪心的时候就是不断的走next,这样就出现了一个O(nm)的算法。
那么倍增怎么做呢?
设nxt[i][j]为第i个区间next 2^j 次后的区间编号,那么:
nxt[i][0]=next[i],nxt[i][j]=nxt[nxt[i][j-1]][j-1
于是就可以做了。
不过这里我要提醒一点:C++的变量名如果用了"next",在HDU是无法通过编译的,我因此贡献了8次CE……
代码
#include <cstring>#include <algorithm>#include <cstdio>#include <cstdlib>#include <cmath>using namespace std;const int N=100000+5;int n,m;int Next[N][20];bool alive[N];//原来的next[N]舍去,nxt[N][20]写作next[N][20]struct Seg{int x,y;bool operator < (const Seg &a) const{if (x==a.x)return y>a.y;return x<a.x;}}a[N];void Thrown(){int n_=0,miny=1e9+1;for (int i=n;i>=1;i--)if (a[i].y>=miny)alive[i]=0;elsealive[i]=1,miny=min(miny,a[i].y);for (int i=1;i<=n;i++)if (alive[i])a[++n_]=a[i];n=n_;}int findx(int x){int le=1,ri=n,mid,ans=n+1;while (le<=ri){mid=(le+ri)>>1;if (a[mid].x==x)return mid;if (a[mid].x>x)ri=mid-1,ans=mid;elsele=mid+1;}return ans;}int solve(int L,int R){int st=findx(L),ans=1,k;if (a[st].y>R)return 0;for (k=0;(1<<k)<=n-st;k++);for (;k>=0;k--)if ((1<<k)<=n-st&&a[Next[st][k]].y<=R)st=Next[st][k],ans+=1<<k;return ans;}int main(){while (~scanf("%d%d",&n,&m)){memset(Next,0,sizeof Next);for (int i=1;i<=n;i++)scanf("%d%d",&a[i].x,&a[i].y),a[i].y--; sort(a+1,a+n+1);Thrown();a[n+1].y=1e9+1;a[0].y=1e9+1;for (int i=n;i>=1;i--){Next[i][0]=findx(a[i].y+1);//即原来的next[i]for (int j=1;(1<<j)<=n-i;j++)Next[i][j]=Next[Next[i][j-1]][j-1];}for (int i=1,L,R;i<=m;i++){scanf("%d%d",&L,&R);printf("%d\n",solve(L,R));}}return 0;}
阅读全文
0 0
- HDU4343Interval query 倍增
- hdu4343 Interval query【贪心+倍增】
- HDU 4343 Interval query 倍增思想, DP
- HDU4343[Interval query]--倍增思想+二分+离散
- HDU 4343 Interval query 离散化+倍增思想
- SPOJ 913 Query on a tree II ( 树链剖分 + 倍增 )
- SPOJ QTREE2 Query on a tree II (倍增LCA)
- HDU 4343 Interval query(倍增思想+贪心)
- SPOJ Query on a tree II (倍增LCA)
- SPOJ Query on a tree II (倍增LCA)
- SPOJ QTREE2 Query on a tree II 倍增lca
- 倍增
- 倍增
- 倍增
- 倍增
- SPOJ 913 QTREE系列- Query on a tree II (倍增LCA)
- SPOJ——QTREE2 - Query on a tree II(树链剖分或者倍增法)
- 倍增时间 倍增...?
- 将二叉搜索树转换成一个排序的双向链表
- java自学-进制
- 前序遍历和中序遍历重建二叉树
- 推荐一个好用小巧的Android引导蒙版(浮层)库
- Excel2JSON Excel转JSON Excel另存为JSON的技巧
- HDU4343Interval query 倍增
- bzoj 4325 NOIP2015 斗地主 (dfs)
- 旋转图片显示背面文字
- 关于另一个博客的一些说明
- JavaScript _proto_与prototype
- 起点
- TCP四次挥手中的TIME_WAIT状态存在的理由
- 51NOD1119
- 常量折叠