zoukankan      html  css  js  c++  java
  • Luogu P5332 [JSOI2019]精准预测

    Link
    对于火星人(u),在时间点(t),我们将其拆成两个点((u,t,0),(u,t,1))表示它的存活状态。
    考虑用( ext{2-SAT})来表示限制。
    那么此时我们有((i,t,0) ightarrow(i,t+1,0),(i,t+1,1) ightarrow(i,t,1))两条边。
    对于限制((0,t,u,v)),我们连((u,t,0) ightarrow(v,t+1,0),(v,t+1,1) ightarrow(u,t,1))
    对于限制((1,t,u,c)),我们连((u,t,1) ightarrow(v,t,0),(v,t,1) ightarrow(u,t,0))
    那么我们要求的就是在选择((u,T+1,0))时有多少个((v,T+1,1))必定被选择,即有多少个((v,T+1,1))((u,T+1,0))的后继中。
    注意到对于每个火星人而言,我们可以只保留它的在时刻(T+1)的点和作为(u)限制时的点,那么点数就是(2(n+m))了。
    求答案用( ext{bitset})优化( ext{DAG})上传递闭包即可,时空复杂度均为(O(frac{n^2}{omega}))(认为(n,m)同阶)。
    空间开不下可以分多次跑。

    #include<map>
    #include<queue>
    #include<bitset>
    #include<cctype>
    #include<cstdio>
    #include<vector>
    #include<algorithm>
    const int N=300007;
    int read(){int x=0,c=getchar();while(isspace(c))c=getchar();while(isdigit(c))(x*=10)+=c&15,c=getchar();return x;}
    int pos[N],deg[N],ans[N];struct node{int c,t,x,y;}a[N];
    std::queue<int>q;std::vector<int>e[N];std::map<int,int>mp[N];std::bitset<10001>s[N],ban;
    void add(int c,int u,int v){e[u+c].push_back(v),e[v+1].push_back(u+!c);}
    int main()
    {
        int t=read(),n=read(),m=read(),cnt=0;
        for(int i=1;i<=m;++i) a[i]={read(),read(),read(),read()},mp[a[i].x][a[i].t]=cnt,cnt+=2;
        for(int i=1;i<=n;++i) mp[i][t+1]=cnt,cnt+=2;
        for(int i=1;i<=m;++i) add(a[i].c,mp[a[i].x][a[i].t],(a[i].c? mp[a[i].y].lower_bound(a[i].t):mp[a[i].y].upper_bound(a[i].t))->second);
        for(int i=1;i<=n;pos[i]=prev(mp[i].end())->second,++i) for(auto l=mp[i].begin(),r=next(l);r!=mp[i].end();l=r,r=next(r)) add(0,l->second,r->second);
        for(int l=1,r;l<=n;l+=10000)
        {
    	r=std::min(l+9999,n),ban.reset();
    	for(int u=0;u<cnt;++u)
    	{
    	    s[u].reset();
    	    for(int v:e[u]) ++deg[v];
    	}
    	for(int i=l;i<=r;++i) s[pos[i]+1][i-l]=1;
    	for(int u=0;u<cnt;++u) if(!deg[u]) q.push(u);
    	for(int u;!q.empty();)
    	{
    	    u=q.front(),q.pop();
    	    for(int v:e[u]) if(s[v]|=s[u],!--deg[v]) q.push(v);
    	}
    	ban.reset();
    	for(int i=l;i<=r;++i) if(s[pos[i]][i-l]) ban[i-l]=1,ans[i]=-1e9;
    	for(int i=1;i<=n;++i) ans[i]+=r-l+1-(s[pos[i]]|ban).count();
        }
        for(int i=1;i<=n;++i) printf("%d ",std::max(ans[i]-1,0));
    }
    
  • 相关阅读:
    引物设计重复性查看
    NCBI获取指定区域基因序列及其引物设计
    视频录制软件——Bandicam使用介绍
    SX知识学习——IGV
    常用网站总结
    计算机知识学习——window上配置perl环境(转)
    ubuntu virtualenv安装
    Windows下使用virtualenv
    linux ssh连接设置
    linux 搭建FTP
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12933959.html
Copyright © 2011-2022 走看看