• [SNOI2017] 炸弹


    link

    线段树优化建图,再跑$tarjan$已成$DAG$,然后反跑拓扑排序即可,因为最小的反倒是连边连的最多的地方,即使方向两边入读为$0$的点,然后在随便跑个计数$dp$即可

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #define mod 1000000007
    using namespace std;
    queue<long long> que;
    inline long long read()
    {
        long long f=1,ans=0;char c;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
        return f*ans;
    }
    long long n,r[500001],p[500001],ll[500001],rr[500001],m;
    long long query_l(long long pos,long long rrr){
        long long l=1,r=n,minn=2<<30-1,mid,ls=pos-rrr;
        while(l<=r){
            mid=l+r>>1;
            if(p[mid]>=ls) minn=min(minn,mid),r=mid-1;
            else l=mid+1;
        }return minn;
    }
    long long query_r(long long pos,long long rrr){
        long long l=1,r=n,maxn=0,mid,lr=pos+rrr;
        while(l<=r){
            mid=l+r>>1;
            if(p[mid]<=lr) maxn=max(maxn,mid),l=mid+1;
            else r=mid-1;
        }return maxn;
    }
    struct node{
        long long u,v,nex;
    }x[10999999];
    long long head[9500001],vis[9500001],cnt,f[9500001],uu[10999999],vv[10999999];
    struct node1{
        long long u,v;
    }s[10999999];
    void add(long long u,long long v){
        x[cnt].u=u,x[cnt].v=v,x[cnt].nex=head[u],head[u]=cnt++;
        s[cnt].u=u,s[cnt].v=v;
    }
    void build(long long k,long long l,long long r){
        if(l==r) {add(k+n,l);return;}
        long long mid=l+r>>1;
        build(k<<1,l,mid),build(k<<1|1,mid+1,r);
        add(k+n,(k<<1)+n),add(k+n,(k<<1|1)+n);
        return;
    }
    void query(long long k,long long l,long long r,long long x,long long y,long long st){
        if(x<=l&&r<=y){add(st,k+n);return;}
        long long mid=l+r>>1;
        if(x<=mid) query(k<<1,l,mid,x,y,st);
        if(mid<y) query(k<<1|1,mid+1,r,x,y,st);
        return;
    }
    long long du[10999999],co[10999999],col,ans[10999999],low[10999999],dfn[10999999],sta[10999999],tot,num;
    void tarjan(long long xx){
        low[xx]=dfn[xx]=++num;
        sta[++tot]=xx;
        for(long long i=head[xx];i!=-1;i=x[i].nex){
            long long v=x[i].v;
            if(!dfn[v]) {tarjan(v);low[xx]=min(low[xx],low[v]);}
            else if(!co[v]) low[xx]=min(low[xx],dfn[v]);
        }
        if(dfn[xx]==low[xx]){
            co[xx]=++col;
            if(xx>=1&&xx<=n) ans[col]++;
            while(sta[tot]!=xx){
                co[sta[tot]]=col;
                if(sta[tot]>=1&&sta[tot]<=n) ans[col]++;
                tot--;
            }tot--;
        }return;
    }
    long long dp[19999999];
    bool cmp(node1 x1,node1 x2){
        if(x1.u==x2.u) return x1.v<x2.v;
        return x1.u<x2.u;
    }
    void reset(){
        for(long long i=1;i<=cnt;i++) s[i].u=co[s[i].u],s[i].v=co[s[i].v];
        sort(s+1,s+cnt+1,cmp);
        m=cnt;
        memset(head,-1,sizeof(head)),cnt=0;
        for(long long i=1;i<=m;i++){
            if(((s[i].u!=s[i].v)&&((s[i].u!=s[i-1].u)||(s[i].v!=s[i-1].v)))) {
                add(s[i].v,s[i].u),du[s[i].u]++;
            }
        }
        for(long long i=1;i<=col;i++) dp[i]=ans[i];
        for(long long i=1;i<=col;i++){
            if(!du[i]) que.push(i);
        }
    }
    void topu(){
        while(!que.empty()){
            long long u=que.front();que.pop();
            for(long long i=head[u];i!=-1;i=x[i].nex){
                dp[x[i].v]+=dp[u];
                du[x[i].v]--;
                if(!du[x[i].v]) que.push(x[i].v);
            }
        }
    }
    long long sum;
    int main()
    {
        memset(head,-1,sizeof(head));
        n=read();
        for(long long i=1;i<=n;i++) p[i]=read(),r[i]=read();
        for(long long i=1;i<=n;i++){
            ll[i]=query_l(p[i],r[i]),rr[i]=query_r(p[i],r[i]);
        }
        build(1,1,n);
        for(long long i=1;i<=n;i++) query(1,1,n,ll[i],rr[i],i);
        for(long long i=1;i<=n;i++)
            if(!dfn[i]) tarjan(i);
        reset();
        topu();
        for(long long i=1;i<=n;i++) 
            sum+=i*dp[co[i]],sum%=mod;
        cout<<sum;
    }
    View Code
  • 相关阅读:
    mysql 慢查询分析工具
    php+redis实现消息队列
    Mysql数据库千万级数据查询优化方案.....
    windows下安装docker详细步骤
    Git基础使用教程
    redis实现消息队列&发布/订阅模式使用
    macos上改变输入法顺序
    ssh动态转发小记
    ubuntu上runsv/runit小记
    使用libcurl下载https地址的文件
  • 原文地址:https://www.cnblogs.com/si-rui-yang/p/9850288.html
Copyright © 2020-2023  润新知