• SCUT


    https://scut.online/p/151

    一块长方形草坪,中线上有一群圆心,可以打开圆心的开关给长方形草坪浇水,求覆盖整个长方形需要的最少的开关。

    一开始不知道怎么处理这些边界点……

    但其实观察到一个事实,首先它是对称的,只考虑上半部分。每个上边界的点被覆盖,则它的垂线必被覆盖。故很显然就需要覆盖最上方的边界。

    所以就是给一堆线段,求最少的线段把上边界完全覆盖。按右边界排序之后贪心就可以了。

    但实际上确实蛮多细节的。尤其是离散化还有最后一个点的覆盖问题。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    double p[200005];
    double l[100005];
    double r[100005];
    
    int n;
    
    pair<int, int> LR[100005];
    
    vector<int> st;
    
    int main() {
    #ifdef Yinku
        freopen("Yinku.in", "r", stdin);
    #endif // Yinku
        double X, Y;
        while(~scanf("%lf%lf", &X, &Y)) {
            st.clear();
    
            Y /= 2.0;
            scanf("%d", &n);
            double x, y;
    
            int sucl = 0;
            int sucr = 0;
    
            int cnt = 0;
            for(int i = 1; i <= n; ++i) {
                scanf("%lf%lf", &x, &y);
                if(y <= Y)
                    continue;
                ++cnt;
                double dx = sqrt(y * y - Y * Y);
                l[cnt] = round((x - dx) * 1e10) / 1e10;
                l[cnt] = max(0.0, l[cnt]);
                r[cnt] = round((x + dx) * 1e10) / 1e10;
                r[cnt] = min(X, r[cnt]);
                p[cnt * 2 - 1] = l[cnt];
                p[cnt * 2] = r[cnt];
                //cout <<"l="<< l[cnt] << endl;
                //cout <<"r="<< r[cnt] << endl;
    
                if(l[cnt] == 0.0)
                    sucl = 1;
                if(r[cnt] == X)
                    sucr = 1;
            }
    
            if(cnt == 0 || sucl == 0 || sucr == 0) {
                puts("-1");
                continue;
            }
    
            sort(p + 1, p + 1 + cnt * 2);
            int tcnt = unique(p + 1, p + 1 + cnt * 2) - (p + 1);
    
            for(int i = 1; i <= cnt; ++i) {
                LR[i].first = lower_bound(p + 1, p + 1 + tcnt, l[i]) - p;
                LR[i].second = lower_bound(p + 1, p + 1 + tcnt, r[i]) - p;
                //cout << "L="<<LR[i].first << " R=" << LR[i].second << endl;
            }
    
            //线段按L顺序排序
            sort(LR + 1, LR + 1 + cnt);
    
            int cur = 0;
            int sum = 0;
            int suc = 1;
            int LRi = 1;
    
            //整个线段是[1,tcnt],结束点不考虑
            for(int i = 1; i < tcnt; ++i) {
                //加入覆盖点i的线段
                while(LRi <= cnt && i >= LR[LRi].first) {
                    //单调栈,存R点最大的若干个
                    while(st.size() && st.back() <= LR[LRi].second)
                        st.pop_back();
                    st.push_back(LR[LRi].second);
                    ++LRi;
                }
    
                //离开i点弹出在i点结束的点
                while(st.size() && st.back() <= i)
                    st.pop_back();
    
                //当前点没有被覆盖
                if(cur <= i) {
                    if(st.empty()) {
                        suc = 0;
                        break;
                    } else {
                        //选最远的一个点进行覆盖
                        cur = st[0];
                        ++sum;
                    }
                }
                //printf("i=%d cur=%d
    ",i,cur);
            }
    
            //强制算上结束点
            if(cur < tcnt)
                sum++;
    
            if(suc)
                printf("%d
    ", sum);
            else
                puts("-1");
        }
    }
    
  • 相关阅读:
    Python中使用PyMySQL
    python实现通用json导入到mysql
    python实现通用excel导入到mysql
    java优化几个小步骤
    日志添加request-id
    Nginx优化
    tomcat8 性能优化参考
    excel空格处理
    spring boot swagger ui使用 nginx 部署后无法使用问题
    Swagger2多包扫描
  • 原文地址:https://www.cnblogs.com/Inko/p/11688952.html
Copyright © 2020-2023  润新知