4444: [Scoi2015]国旗计划|贪心|倍增
2016-03-22 10:34
405 查看
因为没有区间被其他区间包含这个条件,也就是如果li<ljl_{i}那么一定满足ri<rjr_{i},就可以贪心搞一搞了。
假如区间[l,r][l,r]都已经被覆盖,那么可以继续找一个lil_{i}在[l,r][l,r]范围内的最大的一个,继续扩展覆盖的区间,然后再以同样的方式找下一个战士
这样可以按照左端点排序,然后每一个战士要找的下一个战士都是确定的,然后用倍增找出一共需要多少战士就可以了
假如区间[l,r][l,r]都已经被覆盖,那么可以继续找一个lil_{i}在[l,r][l,r]范围内的最大的一个,继续扩展覆盖的区间,然后再以同样的方式找下一个战士
这样可以按照左端点排序,然后每一个战士要找的下一个战士都是确定的,然后用倍增找出一共需要多少战士就可以了
#include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<vector> #include<cmath> #include<queue> #include<set> #include<map> #define ll long long #define N 402020 #define pa pair<int,int> using namespace std; int sc() { int i=0,f=1; char c=getchar(); while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9')i=i*10+c-'0',c=getchar(); return i*f; } struct W{int l,r,p;}a ; int n,m,tot,fa [19],ans ; set<pa>st; bool cmp(W a,W b) { return a.l<b.l; } void solve(int x) { int p=a[x].p,L=a[x].l+m; for(int i=18;i>=0;i--) if(fa[x][i]) if(a[fa[x][i]].r<L) x=fa[x][i],ans[p]+=(1<<i); } int main() { n=sc(),m=sc(); for(int i=1;i<=n;i++) { a[++tot].l=sc(),a[tot].r=sc(),a[tot].p=i; if(a[tot].r<a[tot].l)a[tot].r+=m; ++tot; a[tot].l=a[tot-1].l+m; a[tot].r=a[tot-1].r+m; } sort(a+1,a+tot+1,cmp); st.insert(make_pair(a[tot].l,tot)); for(int i=tot-1;i;i--) { fa[i][0]=(--st.upper_bound(make_pair(a[i].r,0x7FFFFFFF)))->second; st.insert(make_pair(a[i].l,i)); } for(int i=1;i<=18;i++) for(int j=tot;j;j--) fa[j][i]=fa[fa[j][i-1]][i-1]; for(int i=1;i<=tot;i++) if(a[i].p) solve(i); for(int i=1;i<=n;i++) printf("%d ",ans[i]+2); return 0; }
相关文章推荐
- Python 基础—— collections 模块
- 三层架构与MVC的区别
- Spring 一二事(1)
- 对Android中集成支付宝支付流程的总结
- matlab 生成几个聚类点函数nngenc函数
- Zend Framework实现留言本分页功能(附demo源码下载)
- 150. Evaluate Reverse Polish Notation
- 【记录】两年程序生涯的点滴与反思
- JFinal中的AOP
- 坦克大战
- 【Hibernate步步为营】--多对多映射详解
- NYOJ.891_找点问题
- iar工程重命名
- 算法浅谈——字符串相关
- 坦克大战
- 新手做LeetCode N16 3Sum Closest
- 18. 4Sum
- DB2命令行操作指令
- DB2命令行操作指令
- JS元素位置和位置坐标