返回顶部

AcWing - 121 - 赶牛入圈 = 离散化 + 二分 + 尺取

https://www.acwing.com/problem/content/123/

对坐标离散化之后暴力二分枚举边长,然后尺取验证,复杂度\(O(n^2logn)\)

WA了1发因为y坐标没有清空。尺取的那个二分开头是没必要的,还容易错(当没有把坐标偏移到从(1,1)开始就不能这样二分找初始位置)。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

int c, n;

int x[505];
int y[505];

int xx[505];
int yy[505];

int sum[505][505];

int xxtop, yytop;

bool check(int len) {
    int prex = 0, prey = 0;
    //int curx = (upper_bound(xx + 1, xx + 1 + xxtop, len) - xx) - 1;
    //int cury = (upper_bound(yy + 1, yy + 1 + yytop, len) - yy) - 1;
    int curx = 1;
    int cury = 1;
    int tmpy = cury;
    //printf("len=%d x=%d y=%d\n", len, x[curx], y[cury]);
    //printf("len=%d x=%d y=%d\n", len, curx, cury);

    while(curx <= xxtop - 1) {
        while(xx[curx] - xx[prex + 1] >= len)
            ++prex;

        prey = 0;
        cury = tmpy;
        while(cury <= yytop - 1) {
            while(yy[cury] - yy[prey + 1] >= len)
                ++prey;

            //printf("[%d,%d][%d,%d]\n",prex+1,curx,prey+1,cury);
            //printf("[%d,%d][%d,%d]\n",xx[prex+1],xx[curx],yy[prey+1],yy[cury]);
            if(sum[curx][cury] - sum[prex][cury] - sum[curx][prey] + sum[prex][prey] >= c) {
                //puts("TRUE");
                /*printf("prex=%d\n",prex+1);
                printf("prey=%d\n",prey+1);
                printf("curx=%d\n",curx);
                printf("cury=%d\n",cury);
                printf("prex=%d\n",xx[prex+1]);
                printf("prey=%d\n",yy[prey+1]);
                printf("curx=%d\n",xx[curx]);
                printf("cury=%d\n",yy[cury]);*/
                return true;
            }
            ++cury;
        }
        ++curx;
    }
    //puts("FALSE");
    return false;
}

int bs() {
    int l = 1, r = 10001, m;
    while(1) {
        m = (l + r) >> 1;
        if(l == m) {
            if(check(l))
                return l;
            return r;
        }
        if(check(m))
            r = m;
        else
            l = m + 1;
    }
}

int main() {
#ifdef Yinku
    freopen("Yinku.in", "r", stdin);
#endif // Yinku
    scanf("%d%d", &c, &n);
    int minx = 10005, miny = 10005;
    for(int i = 1; i <= n; ++i) {
        scanf("%d", &x[i]);
        scanf("%d", &y[i]);
        minx = min(minx, x[i]);
        miny = min(miny, y[i]);
    }

    for(int i = 1; i <= n; ++i) {
        xx[i] = x[i] = x[i] - minx + 1;
        yy[i] = y[i] = y[i] - miny + 1;
    }
    xx[n + 1] = x[n + 1] = 10005;
    yy[n + 1] = y[n + 1] = 10005;
    sort(xx + 1, xx + 1 + n + 1);
    sort(yy + 1, yy + 1 + n + 1);
    xxtop = unique(xx + 1, xx + 1 + n + 1) - (xx + 1);
    yytop = unique(yy + 1, yy + 1 + n + 1) - (yy + 1);
    for(int i = 1; i <= n + 1; ++i) {
        x[i] = lower_bound(xx + 1, xx + 1 + xxtop, x[i]) - xx;
        y[i] = lower_bound(yy + 1, yy + 1 + yytop, y[i]) - yy;
        //printf("x=%d y=%d\n", x[i], y[i]);
        if(i <= n)
            sum[x[i]][y[i]]++;
    }
    for(int i = 1; i <= xxtop; ++i) {
        for(int j = 1; j <= yytop; ++j) {
            sum[i][j] += (sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1]);
            //printf("%d", sum[i][j] - sum[i - 1][j] - sum[i][j - 1] + sum[i - 1][j - 1]);
            //printf("%d", sum[i][j]);
        }
        //puts("");
    }

    printf("%d\n", bs());
}
posted @ 2019-10-10 22:12  Inko  阅读(177)  评论(0编辑  收藏  举报