• agc015E Mr.Aoki Incubator


    题意:

    数轴上许多黑点,每个点都有一个方向向右的正速度。 

    当两个点在同一个位置上重合时,若其中一个是红色,另一个也变成红色。 

    保证没有相同速度或初始坐标。 

    现问你有多少方法染红一些点,使得无穷久后所有点都被染红。

    $N leq 2*10^5 , X_i,V_i leq 10^9$

    这算是一道比较简单的题吧

    把点按照$X_i$排序后,我们考虑第$i$个点,

    找到一个最小的$L_i$满足$V[L_i] geq V[i]$,和一个最大的$R_i$满足$V[R_i] leq V[i]$

    那么只要在$[L_i,R_i]$之间的点有一个一开始被染红,那么第$i$个点最后也会变成红色

    那么也就是给你$n$个区间,你要求能保证每个区间都至少有一个点染红的方案数

    前缀和优化dp。

    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    #define ll long long
    #define db double
    #define For(i,a,b) for(int i=(a);i<=(b);++i)
    #define Rep(i,a,b) for(int i=(a);i>=(b);--i)
    const int maxn=2e5+7,maxt=23;
    const ll mod=1e9+7;
    int n,W,p[maxn],st[2][maxn][maxt],TOT;
    
    char cc;ll ff;
    template<typename T>void read(T& aa) {
    	aa=0;ff=1; cc=getchar();
    	while(cc!='-'&&(cc<'0'||cc>'9')) cc=getchar();
    	if(cc=='-') ff=-1,cc=getchar();
    	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    	aa*=ff;
    }
    
    struct Node{
    	int x,v;
    	bool operator < (const Node& b) const{return x<b.x;}
    }node[maxn];
    
    struct Li{
    	int l,r;
    	Li(){}
    	Li(int l,int r):l(l),r(r){}
    	bool operator < (const Li& b) const{return r==b.r? l>b.l:r<b.r;}
    }li[maxn];
    
    int getl(int x) {
    	int pos=1;
    	Rep(i,W,0) if(st[0][pos][i]<x) pos+=(1<<i);
    	return pos;
    }
    
    int getr(int x) {
    	int pos=n;
    	Rep(i,W,0) if(st[1][pos][i]>x) pos-=(1<<i);
    	return pos;
    }
    
    ll sum[4*maxn],ql,qr,qx;
    void ud(int pos) {sum[pos]=(sum[pos<<1]+sum[pos<<1|1])%mod;}
    void pd(int pos) {
    	if(sum[pos]!=0) return;
    	sum[pos<<1]=0; sum[pos<<1|1]=0;
    }
     
    void chge(int pos,int l,int r) {
    	if(l>=ql&&r<=qr) {
    		sum[pos]=qx;
    		return;
    	}
    	int mid=(l+r)>>1; pd(pos);
    	if(ql<=mid) chge(pos<<1,l,mid);
    	if(qr>mid) chge(pos<<1|1,mid+1,r);
    	ud(pos);
    }
    
    int main() {
    	read(n); int x,y;
    	For(i,1,n) {
    		read(node[i].x);
    		read(node[i].v);
    		p[i]=node[i].v;
    	}
    	sort(p+1,p+n+1);
    	sort(node+1,node+n+1);
    	For(i,1,n) {
    		node[i].x=i;
    		node[i].v=lower_bound(p+1,p+n+1,node[i].v)-p;
    	}
    	For(i,1,n) st[0][i][0]=st[1][i][0]=node[i].v;
    	for(W=1;(1<<W)<=n;++W) {
    		x=(1<<W-1);
    		For(i,1,n-x) st[0][i][W]=max(st[0][i][W-1],st[0][i+x][W-1]);
    		For(i,n-x+1,n) st[0][i][W]=st[0][i][W-1];
    		Rep(i,n,x+1) st[1][i][W]=min(st[1][i][W-1],st[1][i-x][W-1]);
    		Rep(i,x,1) st[1][i][W]=st[1][i][W-1];
    	} --W;
    	For(i,1,n) {
    		x=getl(node[i].v);
    		y=getr(node[i].v);
    		li[i]=Li(x,y);
    	}
    	sort(li+1,li+n+1);
    	For(i,1,n) p[i]=0;
    	For(i,1,n) p[li[i].r]=max(p[li[i].r],li[i].l);
    	For(i,2,n) p[i]=max(p[i],p[i-1]);
    	TOT=n+1; ql=qr=1; qx=1; chge(1,1,TOT);
    	For(i,1,n) {
    		ql=qr=i+1; qx=sum[1];
    		chge(1,1,TOT);
    		ql=1; qr=p[i]; qx=0;
    		if(ql<=qr) chge(1,1,TOT);
    	}
    	printf("%lld
    ",sum[1]%mod);
    	return 0;
    }
    

      

  • 相关阅读:
    【数据库开发】在Windows上以服务方式运行 MSOPenTech/Redis
    【数据库开发】在Windows上以服务方式运行 MSOPenTech/Redis
    【数据库开发】windows环境下通过c++使用redis
    【数据库开发】windows环境下通过c++使用redis
    【VS开发】【miscellaneous】windows(64位)下使用curl命令
    【VS开发】【miscellaneous】windows(64位)下使用curl命令
    【数据库开发】windows下使用c++调用redis
    【数据库开发】windows下使用c++调用redis
    【VS开发】【miscellaneous】 Windows下配置Git
    【VS开发】【miscellaneous】 Windows下配置Git
  • 原文地址:https://www.cnblogs.com/Serene-shixinyi/p/9092661.html
Copyright © 2020-2023  润新知