zoukankan      html  css  js  c++  java
  • bzoj5017 [Snoi2017]炸弹

    好长时间没写博客了...春季学期的日记似乎是没怎么写, 回头写个总结反思放上来...
    这个题首先一看就是图论题, 看两眼就是需要数据结构优化的图论题, 而且肯定是用线段树. 看三眼发现需要tarjan求一下强连通分量.
    看四眼看出来引爆一个炸弹, 最终能够引爆的所有炸弹一定是一个连续区间内的所有炸弹, 然后就发现只需要求每个炸弹能够引爆的编号最小和最大的炸弹
    也就是从强连通分量缩点之后的DAG上算一下每个SCC能够到达的编号最小/最大的炸弹.
    思路清晰自然, 是个不错的题.

    #include <cstdio>
    #include <vector>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    const int maxn=1000005;
    struct edge{
        int to, next;
    }lst[maxn*40];int len=1;
    int first[maxn];
    void addedge(int a,int b){
        lst[len].to=b;
        lst[len].next=first[a];
        first[a]=len++;
    }
    int N;
    ll X[maxn], R[maxn];
    int left[maxn], right[maxn];
    struct seg{
        static int ID;
        int l,r,id;
        seg* ch[2];
        seg(int a,int b):l(a),r(b){
            if(a==b)id=a;
            else id=++ID;
            ch[0]=ch[1]=0;
        }
    };
    int seg::ID=1;
    void build(seg* &root, int L, int R){
        root = new seg(L,R);
        if(L==R)return;
        build(root->ch[0],L,(L+R)>>1);
        build(root->ch[1],((L+R)>>1)+1,R);
        addedge(root->id, root->ch[0]->id);
        addedge(root->id, root->ch[1]->id);
    }
    void add(seg* rt, int from, int L, int R){
        if(L <= rt->l && rt->r <= R){
            if(from!=rt->id)addedge(from, rt->id);
        }else{
            int mid=(rt->l+rt->r)>>1;
            if(L<=mid)add(rt->ch[0],from,L,R);
            if(R>mid)add(rt->ch[1],from,L,R);
        }
    }
    int dfn[maxn], low[maxn], T;
    int stk[maxn],top=0;
    bool ins[maxn];
    vector<int> scc[maxn];int cntscc=0;
    int belong[maxn];
    void dfs(int x){
        dfn[x]=low[x]=++T;
        stk[top++]=x;ins[x]=true;
        for(int pt=first[x];pt;pt=lst[pt].next){
            if(!dfn[lst[pt].to]){
                dfs(lst[pt].to);
                if(low[lst[pt].to]<low[x])low[x]=low[lst[pt].to];
            }else if(ins[lst[pt].to] && dfn[lst[pt].to]<low[x])low[x]=dfn[lst[pt].to];
        }
        if(low[x] == dfn[x]){
            ++cntscc;
            do{
                scc[cntscc].push_back(stk[--top]);
                belong[stk[top]]=cntscc;
                ins[stk[top]]=false;
            }while(stk[top]!=x);
        }
    }
    void tarjan(){
        for(int i=1;i<=N;++i){
            if(!dfn[i])dfs(i);
        }   
    }
    int lo[maxn], hi[maxn], vis[maxn];
    void DFS(int x){
        vis[x]=1;
        for(vector<int>::iterator p=scc[x].begin();p!=scc[x].end();++p){
            if(1<=(*p) &&(*p)<=N){
                if((*p)>hi[x])hi[x]=*p;
                if((*p)<lo[x])lo[x]=*p;
            }
            for(int pt=first[*p];pt;pt=lst[pt].next){
                int y=belong[lst[pt].to];
                if(!vis[y]){
                    DFS(y);
                }
                if(hi[y]>hi[x])hi[x]=hi[y];
                if(lo[y]<lo[x])lo[x]=lo[y];
            }
        }
    }
    void dp(){
        for(int i=1;i<=cntscc;++i){
            lo[i]=N+1;hi[i]=0;
        }
        for(int i=1;i<=cntscc;++i){
            if(!vis[i])DFS(i);
        }
    }
    int main(){
        scanf("%d",&N);
        for(int i=1;i<=N;++i){
            scanf("%lld%lld",X+i, R+i);
        }
        for(int i=1;i<=N;++i){
            left[i]=lower_bound(X+1,X+N+1, X[i]-R[i])-X;
            right[i]=upper_bound(X+1, X+N+1, X[i]+R[i])-X-1;
        }
        seg::ID=N;
        seg *root;
        build(root, 1, N);//while(1);
        for(int i=1;i<=N;++i){
            add(root,i,left[i],right[i]);
        }
        tarjan();
        dp();
        int ans=0;
        int mod=(int)(1e9+7);
        
        for(int i=1;i<=N;++i){
            ans = (ans + i * 1ll * (hi[belong[i]]-lo[belong[i]]+1))%mod;
        }
        printf("%d
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    用CSS3实现上下左右箭头
    让input框只能输入数字
    给内联元素设置宽高的几种方式
    当文本溢出包含的元素时加省略号之text-overflow
    通过box盒子模型给元素内容设置居中
    CSS3中的字体rem
    封装一个取消事件冒泡的方法
    HTML5 web workes实现多线程
    通过imeMode禁用键盘只能输入数字
    jquery的children方法和css3选择器配合使用
  • 原文地址:https://www.cnblogs.com/liu-runda/p/11169868.html
Copyright © 2011-2022 走看看