zoukankan      html  css  js  c++  java
  • SNOI2017炸弹

    这个东西其实我是不太会的……但是勉强卡过去了。

    首先肯定是建有向图,然后求每个节点能访问的节点个数,最裸的打法就是按照题意枚举建边然后tarjan缩点,用bitset记录一下访问节点,但是bitset开不了那么大,只能拿到50%的分,至于开数组枚举我没有试,目测高不了多少。

    然后思考这样一个问题,我建的那么多边真的有用么。于是只建离他最近的两个点的边,然后直接topsort统计ans,能拿到80%的数据。

    然后就不会了……

    去loj看一眼,有一组小的hack数据,异常难受。

    看看别人的打法,不是直接统计ans,而是记录这个点所能到达的最左点l[x]和最右点r[x],然后r[x]-l[x]+1就是他能引爆的炸弹数。可以AC。

    #include <iostream>
    #include <algorithm>
    #include <cmath>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <queue>
    #include <stack>
    #include <bitset>
    #include <map>
    #define ll long long
    using namespace std;
    struct EDGE {
        int ed, nex;
    } edge[1000500], edgec[1000500];
    int first[500500], firstc[500500], numc, num;
    struct Point {
        ll x, r;
    } p[500500];
    ll read() {
        ll sum = 0;
        int f = 1;
        char x = getchar();
        while (x < '0' || x > '9') {
            if (x == '-')
                f = -1;
            x = getchar();
        }
        while (x >= '0' && x <= '9') {
            sum = sum * 10 + x - '0';
            x = getchar();
        }
        return sum * f;
    }
    ll n, ans1;
    const int mod = 1e9 + 7;
    const int inf=0x7fffffff;
    int dfn[500500], low[500500], sta[50005000], bl[500500], du[500500];
    int ord, sccnum, top,l[500500],r[500500];
    vector<int> scc[500500];
    bool ins[500500];
    void add(int st, int ed) {
        //    cout<<"st="<<st<<" ed="<<ed<<endl;
        edge[++num].ed = ed;
        edge[num].nex = first[st];
        first[st] = num;
    }
    void addc(int st, int ed) {
        //    cout<<"stc="<<st<<" edc="<<ed<<endl;
        edgec[++numc].ed = ed;
        edgec[numc].nex = firstc[st];
        firstc[st] = numc;
    }
    void topsort() {
        queue<int> q;
        for (int i = 1; i <= sccnum; i++)
            if (!du[i])
                q.push(i);
        while (!q.empty()) {
            int x = q.front();
            q.pop();
            for (int i = firstc[x]; i; i = edgec[i].nex) {
                int y = edgec[i].ed;
                du[y]--;
                l[y]=min(l[y],l[x]);
                r[y]=max(r[y],r[x]);
                if (!du[y]) 
                    q.push(y);
            }
        }
    }
    void tarjan(int x) {
        dfn[x] = low[x] = ++ord;
        sta[++top] = x;
        ins[x] = 1;
        for (int i = first[x]; i; i = edge[i].nex) {
            int y = edge[i].ed;
            if (!dfn[y]) {
                tarjan(y);
                low[x] = min(low[x], low[y]);
            } else if (ins[y])
                low[x] = min(low[x], dfn[y]);
        }
        if (dfn[x] == low[x]) {
            sccnum++;
            int p;
            do {
                p = sta[top--];
                ins[p] = 0;
                l[sccnum]=min(l[sccnum],p);
                r[sccnum]=max(r[sccnum],p);
                bl[p] = sccnum;
                scc[sccnum].push_back(p);
            } while (x != p);
        }
    }
    int main() {
        n = read();
        for (int i = 1; i <= n; i++) {
            p[i].x = read();
            p[i].r = read();
        }
        for(int i=1;i<=n;i++){
            l[i]=inf;
            r[i]=-inf;
        }
        for (int i = 1; i <= n; i++){
            for (int j = i + 1; j <= n; j++) {
                if (j == i)
                    continue;
                if (p[j].x - p[j].r <= p[i].x ) {
                    add(j, i);
                    break;
                }
            }
        }
        for (int i = n; i >= 1; i--){
            for (int j = i - 1; j >= 1; j--) {
                if (j == i)
                    continue;
                if ( p[i].x <= p[j].x + p[j].r) {
                    add(j, i);
                    break;
                }
            }
        }
        /*    for(int i=1;i<=n;i++)
                        for(int j=1;j<=n;j++){
                                if(i==j) continue;
                                if(p[i].x-p[i].r<=p[j].x&&p[j].x<=p[i].x+p[i].r)
                                        add(i,j);
                                }*/
        for (int i = 1; i <= n; i++)
            if (!dfn[i])
                tarjan(i);
        for (int i = 1; i <= n; i++) {
            for (int j = first[i]; j; j = edge[j].nex) {
                int y = edge[j].ed;
                if (bl[i] == bl[y])
                    continue;
                addc(bl[y], bl[i]);
                du[bl[i]]++;
            }
        }
            /*    for(int i=1;i<=sccnum;i++){
                        for(int j=0;j<scc[i].size();j++)
                                cout<<scc[i][j]<<" ";
                        cout<<endl;
                }*/
        topsort();
        /*    for(int i=1;i<=sccnum;i++)
                        cout<<ans[i]<<" ";cout<<endl;*/
        for (int i = 1; i <= n; i++) 
            ans1 = (ans1 + 1ll * i * (r[bl[i]]-l[bl[i]]+1)) % mod;
        printf("%lld", ans1);
        return 0;
    }
    View Code

    有点错位,凑合看吧,应该好打。

  • 相关阅读:
    Study Plan The Twelfth Day
    Study Plan The Fifteenth Day
    Study Plan The Seventeenth Day
    Study Plan The Tenth Day
    Study Plan The Eighth Day
    Study Plan The Eleventh Day
    Study Plan The Sixteenth Day
    Study Plan The Thirteenth Day
    Study Plan The Fourteenth Day
    Study Plan The Ninth Day
  • 原文地址:https://www.cnblogs.com/Yu-shi/p/11190767.html
Copyright © 2011-2022 走看看