zoukankan      html  css  js  c++  java
  • [CSP-S模拟测试]:bird(线段树优化DP)

    题目传送门(内部题89)


    输入格式

    第一行两个数$n$和$k$,分别表示小鸟的只数和$R$装弹时间。
    接下来$n$行,每行两个数$l,r$表示$n$只小鸟初始时的头和尾的$x$坐标。


    输出格式

    输出一个答案表示$R$最多能得到多少只猎物。


    样例

    样例输入:

    4 5
    -1 1
    2 4
    5 9
    6 8

    样例输出:

    3


    数据范围与提示

    对于$30\%$的数据:$nleqslant 20,max(|l|,|r|)leqslant 100$。
    对于$60\%$的数据:$nleqslant 5,000,max(|l|,|r|)leqslant 5,000$。
    对于$100\%$的数据:$nleqslant 100,000,max(|l|,|r|)leqslant 500,000$。


    题解

    注意两次开枪之间的间隔只需要在$k$之上就好了,不需要一定是$k$。

    状态转移很好写,在此不再赘述,用线段树优化即可满分。

    但是需要注意的是,如果一直鸟的长度$>k$,那么就会被计数两次,若和避免这样的情况呢?

    用一个数组记录当前点的鸟有多少,再在这只鸟飞走的时候再将其插入线段树,而当前点的答案就是线段树里能覆盖这个点的鸟$+$维护的那个数组的当前点的值。

    因为在鸟飞走后再将其插入,所以就避免了重复计算。

    注意边界问题,即$l,r<0$的情况;具体实现可以参考代码。

    时间复杂度:$Theta(nlog max(|l|,|r|))$。

    期望得分:$100$分。

    实际得分:$100$分。


    代码时刻

    #include<bits/stdc++.h>
    #define L(x) x<<1
    #define R(x) x<<1|1
    using namespace std;
    struct rec{int l,r;}pos[100001];
    int n,k;
    int s[500002],beg[500002],mx;
    int tr[2000010],lz[2000010];
    int ans;
    bool cmp(rec a,rec b){return a.r==b.r?a.l<b.l:a.r<b.r;}
    void pushup(int x){tr[x]=max(tr[L(x)],tr[R(x)]);}
    void pushdown(int x){tr[L(x)]+=lz[x];lz[L(x)]+=lz[x];tr[R(x)]+=lz[x];lz[R(x)]+=lz[x];lz[x]=0;}
    void add(int x,int l,int r,int k,int w)
    {
    	if(l==r){tr[x]=w;return;}
    	int mid=(l+r)>>1;
    	pushdown(x);
    	if(k<=mid)add(L(x),l,mid,k,w);
    	else add(R(x),mid+1,r,k,w);
    	pushup(x);
    }
    void add(int x,int l,int r,int L,int R,int w)
    {
    	if(r<L||R<l)return;
    	if(L<=l&&r<=R){tr[x]+=w;lz[x]+=w;return;}
    	int mid=(l+r)>>1;
    	pushdown(x);
    	add(L(x),l,mid,L,R,w);
    	add(R(x),mid+1,r,L,R,w);
    	pushup(x);
    }
    int ask(int x,int l,int r,int L,int R)
    {
    	if(r<L||R<l)return 0;
    	if(L<=l&&r<=R)return tr[x];
    	int mid=(l+r)>>1;
    	pushdown(x);
    	return max(ask(L(x),l,mid,L,R),ask(R(x),mid+1,r,L,R));
    }
    int main()
    {
    	scanf("%d%d",&n,&k);
    	int top=0;
    	for(int i=1;i<=n;i++)
    	{
    		int l,r;
    		scanf("%d%d",&l,&r);
    		l=max(l,0);if(r<0)continue;
    		l++;r++;s[l]++;s[r+1]--;
    		pos[++top]=(rec){l,r};
    		beg[l]++;mx=max(mx,r+1);
    	}
    	n=top;sort(pos+1,pos+n+1,cmp);
    	for(int i=1;i<=mx;i++)s[i]+=s[i-1];
    	int fail=1,now=0;
    	for(int i=1;i<=mx;i++)
    	{
    		int flag=s[i]+ask(1,1,mx,max(0,i-(k<<1)),max(0,i-k));
    		now+=beg[i];ans=max(ans,flag);
    		add(1,1,mx,i,flag-now);
    		while(fail<=n&&pos[fail].r==i)
    		{
    			now--;
    			add(1,1,mx,pos[fail].l,pos[fail].r,1);
    			fail++;
    		}
    	}
    	printf("%d",ans);
    	return 0;
    }
    

    rp++

  • 相关阅读:
    路由控制
    NodeJS -Express 4.0 用include取代partial
    工程的结构文件
    Express 框架的安装
    iconfont阿里爸爸做的开源图库
    12.文件系统fs
    11.事件驱动events
    10.Node.js核心模块
    Apache CXF实现Web Service(2)——不借助重量级Web容器和Spring实现一个纯的JAX-RS(RESTful) web service
    Apache CXF实现Web Service(1)——不借助重量级Web容器和Spring实现一个纯的JAX-WS web service
  • 原文地址:https://www.cnblogs.com/wzc521/p/11743828.html
Copyright © 2011-2022 走看看