zoukankan      html  css  js  c++  java
  • WF2014 Surveillance

    Description

    给一个环 (n) 个区间,求最小用几个区间覆盖环。

    (1leqslant nleqslant 10^6)

    Solution

    对每个区间求能接上的扩展的最右距离的区间,然后对每个区间作为第一个区间倍增直到完全覆盖。

    Code

    #include<bits/stdc++.h>
    using namespace std;
    int len,n;
    #define MAXN 1000010
    int fa[MAXN][21];
    struct node{int l,r,id;}s[MAXN << 1],u[MAXN << 1];
    int tot = 0;
    bool cmp_l(node a,node b){return a.l < b.l;}
    int main()
    {
    	scanf("%d%d",&len,&n);
    	for(int i = 1;i <= n;++i)scanf("%d%d",&s[i].l,&s[i].r);
    	for(int i = 1;i <= n;++i)if((s[i].r + 1) % len == s[i].l % len){puts("1");return 0;}
    	for(int i = 1;i <= n;++i)if(s[i].r < s[i].l)s[i].r += len;
    	sort(s + 1,s + 1 + n,cmp_l);
    	for(int i = 1;i <= n;++i)
    	{
    		if(i == 1)u[++tot] = s[i];
    		else
    		{
    			if(s[i].r <= u[tot].r)continue;
    			else u[++tot] = s[i];
    		}
    	}
    	n = tot;
    	for(int i = 1;i <= n;++i)s[i] = u[i];
    	for(int i = 1;i <= n;++i)
    	{
    		s[i + n].l = s[i].l + len;
    		s[i + n].r = s[i].r + len;
    	}
    	for(int i = 1;i <= n * 2;++i)s[i].id = i;
    	//for(int i = 1;i <= 2 * n;++i)cout << s[i].l << " " << s[i].r << endl;
    	//cout << endl;
    	for(int i = 1,j = 1;i <= n;++i)
    	{
    		while(j < 2 * n && s[j + 1].l <= s[i].r + 1)++j;
    		fa[i][0] = s[j].id;
    	}
    	//for(int i = 1;i <= 2 * n;++i)cout << fa[i][0] << " ";cout << endl;
    	for(int i = n + 1;i <= 2 * n;++i)if(fa[i - n][0] <= n)fa[i][0] = fa[i - n][0] + n;
    	for(int k = 1;k <= 20;++k)for(int i = 1;i <= 2 * n;++i)fa[i][k] = fa[fa[i][k - 1]][k - 1];
    	int ans = 0x3f3f3f3f;
    	for(int i = 1;i <= n;++i)
    	{//cout << " > ";
    		int pos = i;//cout << i << " : " << endl;
    		int res = 0;
    		for(int k = 20;k >= 0;--k)
    		{
    			if(fa[pos][k] == 0)continue;
    			if(s[fa[pos][k]].r - s[i].l + 1 < len)
    			{//cout << pos << " " << k << " " << fa[pos][k] << endl;
    				pos = fa[pos][k];
    				res += (1 << k);
    			}
    		}//cout << "-> " << s[fa[pos][0]].r - s[i].l << endl;
    		if(s[fa[pos][0]].r - s[i].l + 1 >= len)ans = min(ans,res + 2);//cout << " : " << res << " " << i << endl << endl;
    	}
    	if(ans < 0x3f3f3f3f)cout << ans << endl;
    	else puts("impossible");
    	return 0;
    }
    
  • 相关阅读:
    Java -- 基于JDK1.8的LinkedList源码分析
    Java -- 基于JDK1.8的ArrayList源码分析
    Android -- AsyncTask源码解析
    Android -- 自定义view实现keep欢迎页倒计时效果
    Android -- 《 最美有物》好看的点赞效果
    Android -- Glide框架详解(一)
    Android -- 从源码解析Handle+Looper+MessageQueue机制
    面试 -- 关于Activity的相关知识
    用最简单的一个例子看maven冲突的解决办法
    【跟我一起读 linux 源码 01】boot
  • 原文地址:https://www.cnblogs.com/wjh15101051/p/13543328.html
Copyright © 2011-2022 走看看