Hướng dẫn giải của Chu vi các hình chữ nhật


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 flashmt

uses math;
const fi='';
      fo='';
      maxn=10010;
type ar=array[1..maxn*2] of longint;
var n,nh,nv:longint;
    re:int64;
    x,y,h,v,d,e,xx,yy,xt,yt:ar;
    a:array[1..maxn*9] of longint;
    s:array[1..maxn*9] of int64;

procedure rf;
var i:longint;
begin
     read(n);
     for i:=1 to n do read(x[i*2-1],y[i*2-1],x[i*2],y[i*2]);
     for i:=1 to n*2 do
     begin
          xt[i]:=x[i]; yt[i]:=y[i];
          h[i]:=y[i]; v[i]:=x[i];
          d[i]:=i; e[i]:=i;
     end;
end;

procedure mark;
var i:longint;
begin
     for i:=1 to n do
     begin
          xx[i*2-1]:=x[i*2];
          xx[i*2]:=x[i*2-1];
     end;
     for i:=1 to n*2 do
     begin
          h[i]:=y[i]; v[i]:=x[i];
          d[i]:=i; e[i]:=i;
     end;
end;

procedure sort(var h,d:ar;l,r:longint);
var i,j,x,y,t:longint;
begin
     i:=l; j:=r; x:=h[(i+j) shr 1]; y:=d[(i+j) shr 1] and 1;
     repeat
           while (h[i]<x) or ((h[i]=x) and (d[i] and 1>y)) do inc(i);
           while (h[j]>x) or ((h[j]=x) and (d[j] and 1<y)) do dec(j);
           if i<=j then
           begin
                t:=h[i]; h[i]:=h[j]; h[j]:=t;
                t:=d[i]; d[i]:=d[j]; d[j]:=t;
                inc(i); dec(j);
           end;
     until i>j;
     if i<r then sort(h,d,i,r);
     if l<j then sort(h,d,l,j);
end;

procedure roirac;
var i:longint;
begin
     sort(h,d,1,n*2);
     nh:=1; y[d[1]]:=1;
     for i:=2 to n*2 do
     begin
          if h[i]<>h[nh] then
          begin
               inc(nh);
               h[nh]:=h[i];
          end;
          y[d[i]]:=nh;
     end;
     for i:=1 to n do dec(y[i*2]);
     for i:=1 to n do
     begin
          yy[i*2-1]:=y[i*2];
          yy[i*2]:=y[i*2-1];
     end;
end;

procedure add(node,l,r,x,y,val:longint);
var mid:longint;
begin
     if (l=x) and (r=y) then
     begin
          a[node]:=a[node]+val;
          if a[node]=1 then s[node]:=h[r+1]-h[l];
          if a[node]=0 then
          begin
               if l<r then s[node]:=s[node shl 1]+s[node shl 1+1]
               else s[node]:=0;
          end;
     end
     else
     begin
          mid:=(l+r) shr 1;
          if x<=mid then add(node shl 1,l,mid,x,min(y,mid),val);
          if y>mid then add(node shl 1+1,mid+1,r,max(x,mid+1),y,val);
          if a[node]=0 then s[node]:=s[node shl 1]+s[node shl 1+1];
     end;
end;

procedure pr;
var i,t,last:longint;
begin
     roirac;
     sort(v,e,1,n*2);
     last:=0;
     for i:=1 to n*2 do
     begin
          t:=e[i];
          if xx[t]>x[t] then add(1,1,n*2-1,y[t],yy[t],1)
          else add(1,1,n*2-1,yy[t],y[t],-1);
          re:=re+abs(s[1]-last);
          last:=s[1];
     end;
end;

procedure rotate;
var i:longint;
begin
     for i:=1 to n*2 do
     begin
          x[i]:=yt[i]; y[i]:=xt[i];
     end;
     fillchar(d,sizeof(d),0);
     fillchar(e,sizeof(e),0);
     fillchar(xx,sizeof(xx),0);
     fillchar(yy,sizeof(yy),0);
     fillchar(h,sizeof(h),0);
     fillchar(v,sizeof(v),0);
     fillchar(s,sizeof(s),0);
     fillchar(a,sizeof(a),0);
     nh:=0; nv:=0;
end;

begin
     assign(input,fi); reset(input);
     rf;
     mark;
     pr;
     rotate;
     mark;
     pr;
     writeln(re);
     close(input);
end.

Code mẫu của ladpro98

#include <cstring>
#include <vector>
#include <list>
#include <map>
#include <set>
#include <queue>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <climits>
#include <cstdlib>
#include <ctime>
#include <memory.h>
#include <cassert>
#include <climits>
#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 FORD(i, a, b) for(int i = (a); i > (b); i--)
#define REPD(i, a, b) for(int i = (a); i >=(b); i--)
#define TR(it, a) for(typeof((a).begin()) it = (a).begin(); it != (a).end(); it++)
#define RESET(a, v) memset((a), (v), sizeof((a)))
#define SZ(a) (int((a).size()))
#define ALL(a) (a).begin(), (a).end()
#define PB push_back
#define MP make_pair
#define LL long long
#define LD long double
#define II pair<int, int>
#define X first
#define Y second
#define VI vector<int>

const int N = 33333;
const int M = 4 * N;
int OPEN = 1;
int CLOSE = -1;

using namespace std;

typedef pair<int, int> point;
typedef pair<point, point> rectangle;

struct event {
    int x, l, r, type;
    event(int _x, int _l, int _r, int _t) {
        x = _x; l = _l; r = _r; type = _t;
    }
    bool operator < (const event &that) const{
        return x < that.x;
    }
};

II Min(const II &a, const II &b) {
    if (a.X != b.X) return min(a, b);
    return MP(a.X, a.Y + b.Y);
}

int delay[M]; II MIN[M];
#define ll (id << 1)
#define rr (ll | 1)
struct node {
    int l, r, id;

    void access() {
        if (delay[id] == 0) return;
        MIN[id].X += delay[id];
        if (l != r) {
            delay[ll] += delay[id];
            delay[rr] += delay[id];
        }
        delay[id] = 0;
    }

    node(int _l, int _r, int _id)
        {l = _l; r = _r; id = _id; access();}
    node left()
        {return node(l, l + r >> 1, ll);}
    node right()
        {return node((l + r >> 1) + 1, r, rr);}

    void build() {
        if (l > r) return;
        if (l == r) {MIN[id] = MP(0, 1); return;}
        left().build(); right().build();
        MIN[id] = Min(MIN[ll], MIN[rr]);
    }

    void incRange(int i, int j, int v) {
        if (l > r || r < i || j < l) return;
        if (i <= l && r <= j) {
            delay[id] += v;
            access(); return;
        }
        left().incRange(i, j, v);
        right().incRange(i, j, v);
        MIN[id] = Min(MIN[ll], MIN[rr]);
    }

    II getMin(int i, int j) {
        if (l > r || r < i || j < l) return MP(INT_MAX, 0);
        if (i <= l && r <= j) return MIN[id];
        return Min(left().getMin(i, j), right().getMin(i, j));
    }
};

rectangle rect[N];
vector<event> e;
int n, ans;

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

void sweepLine() {
    node root(0, N - 1, 1);
    root.build();
    FOR(step, 0, 2) {
        int j = 0;
        for(int i = 0; i < SZ(e); i = j + 1) {
            j = i;
            while (j + 1 < SZ(e) && e[j + 1].x == e[i].x) j++;
            vector<II> ranges;
            REP(k, i, j) if (e[k].type == CLOSE) ranges.PB(MP(e[k].l, e[k].r - 1));
            REP(k, i, j)
                root.incRange(e[k].l, e[k].r - 1, step ? -e[k].type : (e[k].type));
            if (!ranges.empty()) {
                sort(ALL(ranges));
                int maxR = ranges[0].Y;
                II tmp = root.getMin(ranges[0].X, ranges[0].Y);
                if (tmp.X == 0) ans += tmp.Y;
                FOR(k, 1, SZ(ranges)) {
                    int l = ranges[k].X, r = ranges[k].Y;
                    if (maxR >= l) l = maxR + 1;
                    if (l > r) continue;
                    tmp = root.getMin(l, r);
                    if (tmp.X == 0) ans += tmp.Y;
                    maxR = max(maxR, r);
                }
            }
        }
        reverse(ALL(e)); swap(OPEN, CLOSE);
    }
}

void process() {
    initEvents();
    sweepLine();
}

void testSegmentTree() {
    const int ADD = 0;
    const int GET = 1;

    int i, j, v, queryType;

    while (cin >> i >> j >> v) {
        node(0, N - 1, 1).incRange(i, j, v);
        FOR(i, 0, 10) cout << node(0, N - 1, 1).getMin(i, i).X << ' '; cout << endl;
    }
}

int main() {
    ios :: sync_with_stdio(0); cin.tie(0);
    cin >> n;
    FOR(i, 0, n)
        cin >> rect[i].X.X >> rect[i].X.Y >> rect[i].Y.X >> rect[i].Y.Y;
    process();
    FOR(i, 0, n) swap(rect[i].X.X, rect[i].X.Y), swap(rect[i].Y.X, rect[i].Y.Y);
    process();
    cout << ans;
    return 0;
}

Code mẫu của RR

//Wishing myself a happy lunar new year with a lot of accept solutions
//Written by Nguyen Thanh Trung
{$R+,Q+}
uses math;
const
  FINP='';
  FOUT='';
  MAXN=10001;
  snode=131072;
var
  f1,f2:text;
  nn,n,sum:longint;
  rect:array[1..MAXN] of record x1,y1,x2,y2:longint; end;
  c,x1,x2,y,typ:array[1..MAXN*2] of longint;
  left,right,all,sl:array[1..snode] of longint;
procedure openF; inline;
begin
  assign(f1,FINP); reset(f1);
  assign(f2,FOUT); rewrite(f2);
end;
procedure closeF; inline;
begin
  close(f1); close(f2);
end;
procedure inp; inline;
begin
  read(f1,n);
  for n:=1 to n do
    with rect[n] do read(f1,x1,y1,x2,y2);
end;
var
  temp:longint;
procedure swap(var a,b:longint); inline;
begin
  temp:=a; a:=b; b:=temp;
end;
var
  mid:longint;
procedure sortC(l,r:longint); inline;
var
  i,j:longint;
begin
  i:=l; j:=r; mid:=c[l+random(r-l+1)];
  repeat
    while c[i]<mid do inc(i);
    while c[j]>mid do dec(j);
    if i<=j then
      begin
        swap(c[i],c[j]);
        inc(i); dec(j);
      end;
  until i>j;
  if i<r then sortC(i,r);
  if l<j then sortC(l,j);
end;
procedure makeC; inline;
var
  i:longint;
begin
  nn:=0;
  for i:=1 to n do
    begin
      inc(nn); c[nn]:=rect[i].x1;
      inc(nn); c[nn]:=rect[i].x2;
    end;
  sortC(1,nn);
  i:=1;
  for nn:=1 to nn do
    if c[nn]>c[i] then
      begin
        inc(i);
        c[i]:=c[nn];
      end;
  nn:=i;
end;
procedure sortH(l,r:longint); inline;
var
  i,j:longint;
begin
  i:=l; j:=r; mid:=y[l+random(r-l+1)];
  repeat
    while y[i]<mid do inc(i);
    while y[j]>mid do dec(j);
    if i<=j then
      begin
        swap(x1[i],x1[j]);
        swap(x2[i],x2[j]);
        swap(y[i],y[j]);
        swap(typ[i],typ[j]);
        inc(i); dec(j);
      end;
  until i>j;
  if i<r then sortH(i,r);
  if l<j then sortH(l,j);
end;
procedure makeH; inline;
var
  i:longint;
begin
  i:=0;
  for n:=1 to n do
    begin
      inc(i); x1[i]:=rect[n].x1; x2[i]:=rect[n].x2; y[i]:=rect[n].y1; typ[i]:=1;
      inc(i); x1[i]:=rect[n].x1; x2[i]:=rect[n].x2; y[i]:=rect[n].y2; typ[i]:=-1;
    end;
  sortH(1,i);
end;
procedure init;
begin
  fillchar(all,sizeof(all),0);
  fillchar(sl,sizeof(sl),0);
end;
procedure update(u,v,k:longint);
  procedure visit(i,l,r:longint); inline;
  var
    mid:longint;
  begin
    if (v<=c[l]) or (c[r+1]<=u) or (l>r) then exit;
    if (u<=c[l]) and (c[r+1]<=v) then
      begin
        all[i]:=all[i]+k;
        if all[i]>0 then
          begin
            sl[i]:=1;
            right[i]:=1;
            left[i]:=1;
          end
        else
          begin
            left[i]:=left[i<<1];
            right[i]:=right[i<<1+1];
            sl[i]:=sl[i<<1]+sl[i<<1+1];
            if right[i<<1]+left[i<<1+1]=2 then dec(sl[i]);
          end;
        exit;
      end;
    mid:=(l+r)>>1;
    visit(i<<1,l,mid);
    visit(i<<1+1,mid+1,r);
    if all[i]>0 then
      begin
        sl[i]:=1;
        right[i]:=1;
        left[i]:=1;
      end
    else
      begin
        left[i]:=left[i<<1];
        right[i]:=right[i<<1+1];
        sl[i]:=sl[i<<1]+sl[i<<1+1];
        if right[i<<1]+left[i<<1+1]=2 then dec(sl[i]);
      end;
  end;
begin
  visit(1,1,nn-1);
end;
procedure solve; inline;
var
  i:longint;
begin
  makeC;
  makeH;
  for i:=1 to 2*n do
    begin
      if sl[1]>0 then sum+=(y[i]-y[i-1])*sl[1];
      update(x1[i],x2[i],typ[i]);
    end;
end;
procedure reverse; inline;
begin
  for n:=1 to n do
    with rect[n] do
      begin
        swap(x1,y1);
        swap(x2,y2);
      end;
end;
procedure ans; inline;
begin
  writeln(f2,sum<<1);
end;
begin
  openF;
  inp;
  sum:=0;
  solve;
  init;
  reverse;
  solve;
  ans;
  closeF;
end.

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.