日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Picture POJ - 1177(矩形周长并))

發(fā)布時(shí)間:2023/12/3 编程问答 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Picture POJ - 1177(矩形周长并)) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Picture POJ - 1177

題目:

多個(gè)矩陣相交在一起,問新圖形的周長(zhǎng)是多少

題解:

參考題解

周長(zhǎng)分為兩部分:橫線和豎線
橫線計(jì)算方法:現(xiàn)在總區(qū)間被覆蓋的長(zhǎng)度和上一次總區(qū)間被覆蓋的長(zhǎng)度之差的絕對(duì)值
那么我們只需要從上往下,再從左往右掃描兩次即可
但是這樣需要兩次,有沒有更簡(jiǎn)化的方法:

現(xiàn)在我們打算一次自上而下的掃描把橫線豎線都算出來
橫線的算法和上面說的方法一樣:現(xiàn)在這次總區(qū)間被覆蓋的長(zhǎng)度和上一次總區(qū)間被覆蓋的長(zhǎng)度之差的絕對(duì)值
我們用線段樹來記錄一些信息:

  • l,r :該節(jié)點(diǎn)代表的線段的左右端點(diǎn)坐標(biāo)
  • len:這個(gè)區(qū)間被覆蓋的長(zhǎng)度(即計(jì)算時(shí)的有效長(zhǎng)度)
  • s:表示這個(gè)區(qū)間被覆蓋率多次
  • lc,rc:標(biāo)記這個(gè)節(jié)點(diǎn)的左右兩個(gè)端點(diǎn)是否被覆蓋(0表示沒有,1表示有)
  • sum:表示這個(gè)區(qū)間有多少條不連續(xù)的線段
  • 注意:這個(gè)sum涉及到了豎線的計(jì)算
    若區(qū)間[0,10]被[1,2][4,5]覆蓋,則num = 2

    若區(qū)間[0,10]被[1,3][4,5]覆蓋,則num = 1(兩區(qū)間剛好連在一起)

    若區(qū)間[0,10]被[1,5][2,6]覆蓋,則num = 1(兩區(qū)間連起來還是一段)
    這樣就可以計(jì)算豎線:
    豎線的長(zhǎng)度=【下一條即將被掃到的橫線的高度 - 現(xiàn)在掃到的橫線的高度】* 2 * num
    乘2是因?yàn)槊織l線段有兩個(gè)端點(diǎn)
    有num個(gè)不相交的橫線,向下劃動(dòng)h,不就形成長(zhǎng)度為h的2 * num個(gè)豎線

    代碼:

    #include <algorithm> #include <cmath> #include <cstdio> #include <cstring> #include <iostream> using namespace std; #define ls i << 1 #define rs i << 1 | 1 #define m(i) ((tr[i].l + tr[i].r) >> 1) typedef long long ll; const int N= 5007; const int X= 20007; const int inf= 1 << 29; struct Edge {int l, r;int h;int f;bool operator<(const Edge& a) const{return h < a.h;} } edge[N * 2]; struct tree {int l, r;int len;int s;bool lc, rc; //表示這個(gè)節(jié)點(diǎn)代表的區(qū)間左右兩個(gè)端點(diǎn)是否被覆蓋int num; //這個(gè)區(qū)間有多少不連續(xù)到線段 } tr[X * 4]; void pushup(int i) {if (tr[i].s) {tr[i].len= tr[i].r - tr[i].l + 1;tr[i].lc= tr[i].rc= 1;tr[i].num= 1;}else if (tr[i].l == tr[i].r) {tr[i].len= 0;tr[i].lc= tr[i].rc= 0;tr[i].num= 0;}else {tr[i].len= tr[ls].len + tr[rs].len;tr[i].lc= tr[ls].lc;tr[i].rc= tr[rs].rc;tr[i].num= tr[ls].num + tr[rs].num - (tr[ls].rc & tr[rs].lc);} } void build(int i, int l, int r) {tr[i].l= l;tr[i].r= r;tr[i].s= tr[i].len= 0;tr[i].lc= tr[i].rc= tr[i].num= 0;if (l == r)return;int mid= m(i);build(ls, l, mid);build(rs, mid + 1, r); } void update(int i, int l, int r, int xx) {if (l == tr[i].l && tr[i].r == r) {tr[i].s+= xx;pushup(i);return;}int mid= m(i);if (r <= mid)update(ls, l, r, xx);else if (l > mid)update(rs, l, r, xx);else {update(ls, l, mid, xx);update(rs, mid + 1, r, xx);}pushup(i); } int main() {int n;while (scanf("%d", &n) != EOF) {int x1, x2, y1, y2, mx= -inf, mn= inf;int tot= 0;for (int i= 0; i < n; i++) {scanf("%d%d%d%d", &x1, &y1, &x2, &y2);mx= max(mx, max(x1, x2));mn= min(mn, min(x1, x2));Edge& t1= edge[tot];Edge& t2= edge[tot + 1];t1.l= t2.l= x1;t1.r= t2.r= x2;t1.h= y1;t1.f= 1;t2.h= y2;t2.f= -1;tot+= 2;}sort(edge, edge + tot);//數(shù)據(jù)小不用離散化int ans= 0;int last= 0;build(1, mn, mx - 1);for (int i= 0; i < tot; i++) {update(1, edge[i].l, edge[i].r - 1, edge[i].f);ans+= abs(tr[1].len - last);ans+= (edge[i + 1].h - edge[i].h) * 2 * tr[1].num;last= tr[1].len;}printf("%d\n", ans);}return 0; }

    總結(jié)

    以上是生活随笔為你收集整理的Picture POJ - 1177(矩形周长并))的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。