Hướng dẫn giải của ĐINH GHIM


Chỉ dùng lời giải này khi không có ý tưởng, và đừng copy-paste code từ lời giải này. Hãy tôn trọng người ra đề và người viết lời giải.
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.

Lưu ý: Các code mẫu dưới đây chỉ mang tính tham khảo và có thể không AC được bài tập này

Code mẫu của happyboy99x

#include <iostream>
#include <cassert>
#include <cstdio>
using namespace std;

const int INF = (int) 2e9 + 7;

long long calc(long long minX, long long minY, long long maxY) {
    while ((minX + minY) % 2 != 0) ++minY;
    while ((minX + maxY) % 2 != 0) --maxY;
    if (minY > maxY) return 0;
    return (maxY - minY + 2) / 2;
}

int main() {
#ifndef ONLINE_JUDGE
    assert(freopen("pinpos.inp", "r", stdin));
    assert(freopen("pinpos.out", "w", stdout));
#endif
    ios::sync_with_stdio(false);
    int n; cin >> n;
    long long minX = -INF;
    long long maxX = INF;
    long long minY = -INF;
    long long maxY = INF;
    for (int i = 0; i < n; ++i) {
        long long x[4];
        long long y[4];
        for (int i = 0; i < 4; ++i)
            cin >> x[i] >> y[i];
        long long lowX = INF;
        long long highX = -INF;
        long long lowY = INF;
        long long highY = -INF;
        for (int j = 3, i = 0; i < 4; j = i++) {
            if ((x[i] < x[j]) == (y[i] < y[j])) {
                lowX = min(lowX, x[i] - y[i]);
                highX = max(highX, x[i] - y[i]);
            } else {
                lowY = min(lowY, x[i] + y[i]);
                highY = max(highY, x[i] + y[i]);
            }
        }
        minX = max(minX, lowX);
        maxX = min(maxX, highX);
        minY = max(minY, lowY);
        maxY = min(maxY, highY);
    }
    ++minX;
    ++minY;
    --maxX;
    --maxY;
    if (minX > maxX || minY > maxY) {
        cout << 0 << '\n';
    } else {
        cout << calc(minX, minY, maxY) * ((maxX - minX + 2) / 2) + calc(minX + 1, minY, maxY) * ((maxX - minX + 1) / 2) << '\n';
    }
    return 0;
}

Code mẫu của ladpro98

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cassert>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <ctime>
#include <iomanip>
#include <cstdlib>
#include <cstring>
#include <string>
#define FOR(i, a, b) for(int i = (a); i < (b); i++)
#define REP(i, a, b) for(int i = (a); i <=(b); i++)
#define REPD(i, a, b) for(int i = (a); i >=(b); i--)
#define TR(i, a) for(typeof((a).begin()) i = (a).begin(); i != (a).end(); i++)
#define ALL(a) (a).begin(), (a).end()
#define SZ(a) (int((a).size()))
#define VI vector<int>
#define LL long long
#define LD long double
#define II pair<LL, LL>
#define X first
#define Y second
#define MP make_pair
#define PB push_back
const int N = 100005;
const int oo = 1000000009;
using namespace std;

typedef vector<II> rectangle;

void operator -= (II &a, II b) {a.X -= b.X; a.Y -= b.Y;}
int ccw(II a, II b, II c) {
    c -= b; b -= a;
    if (b == MP(0ll, 0ll) || c == MP(0ll, 0ll)) return -1;
    if (b.X * c.Y == b.Y * c.X) return -1;
    return b.X * c.Y > b.Y * c.X;
}

rectangle rect[N];
int n;

bool insideAll(II p) {
    FOR(i, 0, n) {
        bool ok = 0; int dir = -1;
        rect[i].PB(rect[i][0]);
        FOR(j, 0, 4) {
            int now = ccw(p, rect[i][j], rect[i][j + 1]);
            if (now == -1) return 0;
            if (dir == -1) dir = now;
            else if (now != dir) return 0;
        }
    }
    return 1;
}

void naive() {
    int ans = 0;
    REP(i, -100, 100) REP(j, -100, 100)
    if (insideAll(MP(i, j))) {
        //cout << i << ' ' << j << endl;
        ans++;
    }
    cout << ans << endl;
}

void refineRects() {
    FOR(i, 0, n) {
        FOR(j, 0, 4)
            rect[i][j] = MP(rect[i][j].X + rect[i][j].Y, rect[i][j].X - rect[i][j].Y);
        sort(ALL(rect[i]));
    }
    /*
    FOR(i, 0, n) {
        TR(it, rect[i]) cout << it -> X << ' ' << it -> Y << "  ";
        cout << endl;
    }
    */
}

struct event {
    int x, l, r, type;
    event(int _x, int _l, int _r, int _y) {
        x = _x; l = _l; r = _r; type = _y;
    }
    bool operator < (const event &b) const {
        return (x != b.x) ? (x < b.x) : (type > b.type);
    }
};
vector<event> e;

const int OPEN = 0;
const int CLOSE = 1;

void initEvents() {
    FOR(i, 0, n) {
        e.PB(event(rect[i][0].X, rect[i][0].Y, rect[i][1].Y, OPEN));
        e.PB(event(rect[i][2].X, rect[i][0].Y, rect[i][1].Y, CLOSE));
    }
    sort(ALL(e));
}

LL optimal() {
    refineRects();
    initEvents();
    //TR(it, e) cout << (it -> x) << ' ' << (it -> l) << ' ' << (it -> r) << ' ' << (it -> type) << endl;
    int cnt = 0, l = -oo, r = oo, u, d;
    TR(it, e) {
        int x = it -> x, ll = it -> l, rr = it -> r, type = it -> type;
        if (type == CLOSE && cnt < n) return 0;
        if (type == CLOSE) {
            d = x;
            LL height = d - u - 1, width = r - l - 1;
            int h = (height % 2 + 2) % 2;
            int w = (width % 2 + 2) % 2;
            //cout << l << ' ' << r << ' ' << u << ' ' << d << endl;
            if (h == 0 && w == 0) return (height) * (width / 2);
            if (h == 1 && w == 0) return (height) * (width / 2);
            if (h == 0 && w == 1) return (height / 2) * (width);
            if (h == 1 && w == 1) {
                if ((u % 2 + 2) % 2 == (l % 2 + 2) % 2)
                    return (width / 2 + 1) * (height / 2 + 1) + (width / 2) * (height / 2);
                else
                    return (width / 2 + 1) * (height / 2) + (width / 2) * (height / 2 + 1);
            }
        }
        u = x;
        l = max(l, ll);
        r = min(r, rr);
        cnt++;
    }
    return 0;
}

int main() {
    ios :: sync_with_stdio(0); cin.tie(0);
    cin >> n;
    int x, y;
    int maxCoord = 0;
    FOR(i, 0, n) {
        FOR(j, 0, 4) {
            cin >> x >> y;
            rect[i].PB(MP(x, y));
            maxCoord = max(maxCoord, max(abs(x), abs(y)));
        }
    }
    if (n <= 100 && maxCoord <= 100)
        naive();
    else
        cout << optimal();
    return 0;
}

Code mẫu của RR

#include <set>
#include <map>
#include <list>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iomanip>
#include <complex>
#include <iostream>
#include <algorithm>

#include <ctime>
#include <deque>
#include <bitset>
#include <cctype>
#include <utility>
#include <cassert>
using namespace std;

#define FOR(i,a,b) for(int i=(a),_b=(b); i<=_b; i++)
#define FORD(i,a,b) for(int i=(a),_b=(b); i>=_b; i--)
#define REP(i,a) for(int i=0,_a=(a); i<_a; i++)
#define EACH(it,a) for(__typeof(a.begin()) it = a.begin(); it != a.end(); ++it)

#define DEBUG(x) { cout << #x << " = " << x << endl; }
#define PR(a,n) { cout << #a << " = "; FOR(_,1,n) cout << a[_] << ' '; cout << endl; }
#define PR0(a,n) { cout << #a << " = "; REP(_,n) cout << a[_] << ' '; cout << endl; }

int main() {
    ios :: sync_with_stdio(false); cin.tie(NULL);
    cout << (fixed) << setprecision(6);
    int n; cin >> n;
    long long oo = 1000111000111LL;
    long long min_sum = -oo, min_diff = -oo, max_sum = oo, max_diff = oo;
    FOR(i,1,n) {
        long long x[4], y[4];
        long long cur_min_sum, cur_max_sum, cur_min_diff, cur_max_diff;
        REP(t,4) {
            cin >> x[t] >> y[t];
            if (t == 0) {
                cur_min_sum = cur_max_sum = x[t] + y[t];
                cur_min_diff = cur_max_diff = x[t] - y[t];
            }
            cur_min_sum = min(cur_min_sum, x[t] + y[t]);
            cur_max_sum = max(cur_max_sum, x[t] + y[t]);
            cur_min_diff = min(cur_min_diff, x[t] - y[t]);
            cur_max_diff = max(cur_max_diff, x[t] - y[t]);
        }
        min_sum = max(min_sum, cur_min_sum);
        max_sum = min(max_sum, cur_max_sum);
        min_diff = max(min_diff, cur_min_diff);
        max_diff = min(max_diff, cur_max_diff);
    }
    min_sum += 1; max_sum -= 1;
    min_diff += 1; max_diff -= 1;
//    cout << min_sum << ' ' << max_sum << "   " << min_diff << ' ' << max_diff << endl;
    long long res = 0;
    FOR(d,0,1) {
        long long diff_from = min_diff; while (abs(diff_from % 2) != abs(d)) ++diff_from;
        long long diff_to = max_diff; while (abs(diff_to % 2) != abs(d)) --diff_to;
        if (diff_from > diff_to) continue;

        long long diff = diff_from;
        long long y_from = (min_sum - diff) / 2;
        if (y_from * 2 < min_sum-diff) ++y_from;
        long long y_to = (max_sum - diff) / 2;
        if (y_to * 2 > max_sum-diff) --y_to;

        if (y_from <= y_to)
            res += ((y_to - y_from) + 1) * ((diff_to - diff_from) / 2 + 1);

//        cout << d << "   " << diff_from << ' ' << diff_to << "   " << y_from << ' ' << y_to << endl;
    }
    cout << res << endl;
    return 0;
}

Code mẫu của skyvn97

#include<algorithm>
#include<cstdio>
#include<iostream>
#include<vector>
#define FOR(i,a,b) for (int i=(a),_b=(b);i<=_b;i=i+1)
#define REP(i,n) for (int i=0,_n=(n);i<_n;i=i+1)
#define fi   first
#define se   second
using namespace std;
typedef unsigned long long ull;
const int INF=(int)2e9+7;
int n,minAdd,maxAdd,minSub,maxSub;
void readRectangle(void) {
    vector<pair<int,int> > a;
    REP(i,4) {
        int x,y;
        scanf("%d%d",&x,&y);
        a.push_back(make_pair(x,y));
    }
    int minA,maxA,minS,maxS;
    REP(i,4) REP(j,4) if (i!=j) REP(k,4) if (i!=k && j!=k) REP(l,4) if (i!=l && j!=l && k!=l) {
        if (a[i].fi+a[i].se==a[j].fi+a[j].se && a[k].fi+a[k].se==a[l].fi+a[l].se) {
            minA=a[i].fi+a[i].se;
            maxA=a[k].fi+a[k].se;
        }
        if (a[i].fi-a[i].se==a[j].fi-a[j].se && a[k].fi-a[k].se==a[l].fi-a[l].se) {
            minS=a[j].fi-a[j].se;
            maxS=a[l].fi-a[l].se;
        }
    }
    if (minA>maxA) swap(minA,maxA);
    if (minS>maxS) swap(minS,maxS);
    minAdd=max(minAdd,minA+1);
    maxAdd=min(maxAdd,maxA-1);
    minSub=max(minSub,minS+1);
    maxSub=min(maxSub,maxS-1);
}
ull countOdd(int l,int r) {
    if (l%2==0) l++;
    if (r%2==0) r--;
    if (l>r) return (0);
    return ((1ULL+r-l)/2+1);
}
ull countEven(int l,int r) {
    if (l%2!=0) l++;
    if (r%2!=0) r--;
    if (l>r) return (0);
    return ((1ULL+r-l)/2+1);
}
int main(void) {
    int n;
    scanf("%d",&n);
    minAdd=minSub=-INF;
    maxAdd=maxSub=INF;
    REP(zz,n) readRectangle();
    cout<<1ULL*countOdd(minAdd,maxAdd)*countOdd(minSub,maxSub)
         +1ULL*countEven(minAdd,maxAdd)*countEven(minSub,maxSub)<<endl;
    return 0;
}

Bình luận

Hãy đọc nội quy trước khi bình luận.


Không có bình luận tại thời điểm này.