• CF1175E Minimal Segment Cover 题解


    题意:给出(n)个形如([l,r])的线段。(m)次询问,每次询问区间([x,y]),问至少选出几条线段,使得区间([x,y])的任何一个部位都被至少一条线段覆盖。

    首先有一个显然的贪心,设询问区间为([l,r]),则所取的区间最靠左的一个的左端点必定小于等于(l),并且要使这个区间尽可能地向右延伸。
    取完第一个之后,重复以上的贪心,直至满足条件,那么这样的答案必定是最小的。

    但是这样的时间复杂度是(O(nm))的,所以要考虑优化,优化方法是用倍增,每次向右跳(2^i)条线段,那么复杂度就变成(O(nlog m))了。于是本题就解决了。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define N 200005
    #define M 500005
    inline int read()
    {
    	char ch=getchar();
    	while(!isdigit(ch)) ch=getchar();
    	int ans=0;
    	while(isdigit(ch))
    	{
    		ans=ans*10+ch-48;
    		ch=getchar();
    	}
    	return ans;
    }
    int suf[M][25];
    
    int main()
    {
    	int n,m;
    	cin>>n>>m;
    	int x,y;
    	for(int i=1;i<=n;i++)
    	{
    		x=read(),y=read();
    		x++;
    		if(suf[x][0]<y)
    		{
    			suf[x][0]=y;
    		}
    	}
    	for(int i=1;i<=M;i++)
    	{
    		suf[i][0]=max(suf[i][0],suf[i-1][0]);
    	}
    	for(int i=1;i<=19;i++)
    	{
    		for(int j=1;j<=M;j++)
    		{
    			suf[j][i]=suf[suf[j][i-1]+1][i-1];
    		}
    	}
    	for(int i=1;i<=m;i++)
    	{
    		x=read(),y=read();
    		int ans=0;
    		for(int j=19;j>=0;j--)
    		{
    			if(suf[x+1][j]<y&&suf[x+1][j]>x)
    			{
    				x=suf[x+1][j];
    				ans+=(1<<j);
    			}
    		}
    		ans++;x=suf[x+1][0];
    		if(x<y) printf("-1
    ");
    		else printf("%d
    ",ans);
    	}
    	return 0;
    }
    

    多努力可以改变菜的现实 /kk

    来源:https://www.cnblogs.com/wasa855/

    转载请注明出处

  • 相关阅读:
    python 协程
    python 进程池的使用
    python 多进程数据交互及共享
    python 多进程
    技术博客与技术日记
    理解闭包
    jWriter一个基于jQuery的阅读写作网站的效果库
    ubuntu下phpmyadmin配置问题解决
    避免明文保存用户密码
    如何用css实现类似简书的纵向导航/竖排导航
  • 原文地址:https://www.cnblogs.com/wasa855/p/10989032.html
Copyright © 2020-2023  润新知