• 【CF377D】Developing Game(扫描线)


    题目链接

    • \(n\) 个物品,第 \(i\) 个物品特征值为 \(v_i\),且只能与特征值在 \([l_i,r_i]\) 范围内的物品同时选择​。
    • 求最多能同时选出多少物品,并给出一种最优方案。
    • \(1\le n\le 10^5\)\(1\le l_i\le v_i\le r_i\le3\times10^5\)

    几何转化+扫描线

    显然就是要让选出的物品满足 \(\max\{l_i\}\le\min\{v_i\}\)\(\max\{v_i\}\le\min\{r_i\}\)

    \(\max\{l_i\}\le\min\{v_i\}\) 可以看作是线段 \([l_i,v_i]\) 有交,同样 \(\max\{v_i\}\le\min\{r_i\}\) 可以看作是线段 \([v_i,r_i]\) 有交。

    双重限制只要转化为二维问题,可以看作是以 \((l_i,v_i)\) 为左上角,\((v_i,r_i)\) 为右下角的矩形有交。

    那么只要求出一个点,使得覆盖它的矩形个数最大。

    这是经典的扫描线问题。

    最后构造方案只要判断一下求出的点是否在每个矩形内即可。

    代码:\(O(n\log V)\)

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Rg register
    #define RI Rg int
    #define Cn const
    #define CI Cn int&
    #define I inline
    #define W while
    #define N 100000
    #define V 300000
    #define Pr pair<int,int>
    using namespace std;
    int n,v[N+5],l[N+5],r[N+5];pair<Pr,int> t;struct OP {int op,x,l,r;I bool operator < (Cn OP& o) Cn {return x<o.x;}}s[2*N+5];
    namespace FastIO
    {
    	#define FS 100000
    	#define tc() (FA==FB&&(FB=(FA=FI)+fread(FI,1,FS,stdin),FA==FB)?EOF:*FA++)
    	#define pc(c) (FC==FE&&(clear(),0),*FC++=c)
    	int OT;char oc,FI[FS],FO[FS],OS[FS],*FA=FI,*FB=FI,*FC=FO,*FE=FO+FS;
    	I void clear() {fwrite(FO,1,FC-FO,stdout),FC=FO;}
    	Tp I void read(Ty& x) {x=0;W(!isdigit(oc=tc()));W(x=(x<<3)+(x<<1)+(oc&15),isdigit(oc=tc()));}
    	Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
    	Tp I void write(Ty x) {W(OS[++OT]=x%10+48,x/=10);W(OT) pc(OS[OT--]);pc(' ');}
    }using namespace FastIO;
    class SegmentTree
    {
    	private:
    		#define PT CI l=1,CI r=V,CI rt=1
    		#define LT l,mid,rt<<1
    		#define RT mid+1,r,rt<<1|1
    		#define PU(x) (G[x]=max(G[x<<1],G[x<<1|1]),G[x].first+=F[x])
    		#define T(x,v) (G[x].first+=v,F[x]+=v)
    		pair<int,int> G[V<<2];int F[V<<2];
    	public:
    		I void Bd(PT) {if(l==r) return (void)(G[rt].second=l);RI mid=l+r>>1;Bd(LT),Bd(RT),PU(rt);}
    		I void U(CI L,CI R,CI v,PT) {if(L<=l&&r<=R) return (void)T(rt,v);RI mid=l+r>>1;L<=mid&&(U(L,R,v,LT),0),R>mid&&(U(L,R,v,RT),0),PU(rt);}//区间加
    		I pair<int,int> Q() {return G[1];}//全局询问
    }S;
    int main()
    {
    	RI i,j;for(read(n),i=1;i<=n;++i) read(l[i],v[i],r[i]),s[i]=(OP){1,l[i],v[i],r[i]},s[i+n]=(OP){-1,v[i]+1,v[i],r[i]};//转化成矩形
    	for(sort(s+1,s+2*n+1),S.Bd(),i=j=1;i<=V;++i) {W(j<=2*n&&s[j].x==i) S.U(s[j].l,s[j].r,s[j].op),++j;t=max(t,make_pair(S.Q(),i));}//扫描线
    	RI x=t.second,y=t.first.second;for(printf("%d\n",t.first.first),i=1;i<=n;++i) l[i]<=x&&x<=v[i]&&v[i]<=y&&y<=r[i]&&(write(i),0);return clear(),0;//判断点是否在矩形内
    }
    
  • 相关阅读:
    java并发之CountDownLatch
    在字符串中找出连续最长的数字串
    201301 JAVA题目0-1级
    linux vi 快捷键
    并行流水线、搜索、排序
    JDK中的Future模式
    Disruptor
    Unsafe类 AtomicReference AtomicStampedReference AtomicIntegerArray AtomicIntegerFieldUpdater vector SynchronousQueue
    java 虚拟机 分区 及 GC
    java 虚拟机对锁对优化
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/CF377D.html
Copyright © 2020-2023  润新知