POJ 1177 Picture & hdu 1828 Picture(掃描線)

來源:互聯網
上載者:User

題意:給你n個矩形,要你求出矩形並的輪廓周長。
在做這題之前,建議先解決POJ1151。

在求矩形並面積的時候,我們記錄了線段投影到y軸上被覆蓋的長度,這題同樣要記錄這個值以得到y軸上屬於輪廓的邊長(當然,不是簡單地把這個長加進去,而是加變化值)。不同的是,還要記錄,y軸上有連續的幾段。比如,這時候有兩個線段,線段a(line[i]表示),線段b(line[i-1]),a和b並不相鄰,即這時候,在y軸上有兩條線段,那麼在x軸方向上的屬於輪廓的長度就是2*2*(line[i].x-line[i-1].x),這樣就可以解決這個問題了。(不過discuss裡的資料過不了,當矩形的邊重合在一起,上面的作法對y軸方向上對輪廓的選擇就出現問題了,因為改變數就不一定是輪廓了。)

/*代碼風格更新後 */#include <iostream>#include <cstring>#include <cstdio>#include <vector>#include <map>#include <algorithm>using namespace std;#define LL(x) (x<<1)#define RR(x) (x<<1|1)#define MID(a,b) (a+((b-a)>>1))const int N=10005;int iabs(int x){return x>0?x:-x;}struct Line{int x,y1,y2,flag;Line(){}Line(int a,int b,int c,int d){ x=a;y1=b;y2=c;flag=d; }bool operator<(const Line&b)const{ return x<b.x; }};int n;vector<int> y;vector<Line> line;map<int,int>H;struct node{int lft,rht;int len,cnt,flag;bool isl,isr;int mid(){return MID(lft,rht);}void init(){len=cnt=isl=isr=0;}void fun(int valu){flag+=valu; cnt+=valu;if(flag>0) {isl=isr=1;len=y[rht]-y[lft];}else isl=isr=0,len=0;}};struct Segtree{node tree[N*4];void up(int ind){if(tree[ind].flag>0) {tree[ind].isl=tree[ind].isr=1;tree[ind].cnt=1;tree[ind].len=y[tree[ind].rht]-y[tree[ind].lft];}else if(tree[ind].lft+1==tree[ind].rht){tree[ind].len=0;tree[ind].cnt=0;tree[ind].isl=0;tree[ind].isr=0;}else{tree[ind].len=tree[LL(ind)].len+tree[RR(ind)].len;tree[ind].cnt=tree[LL(ind)].cnt+tree[RR(ind)].cnt;if(tree[LL(ind)].isr&&tree[RR(ind)].isl) tree[ind].cnt--;tree[ind].isl=tree[LL(ind)].isl;tree[ind].isr=tree[RR(ind)].isr;}}void build(int lft,int rht,int ind){tree[ind].lft=lft;tree[ind].rht=rht;tree[ind].init();if(lft+1!=rht){int mid=tree[ind].mid();build(lft,mid,LL(ind));build(mid,rht,RR(ind));}}void updata(int st,int ed,int ind,int valu){int lft=tree[ind].lft,rht=tree[ind].rht;if(st<=lft&&rht<=ed) tree[ind].fun(valu);else {int mid=tree[ind].mid();if(st<mid) updata(st,ed,LL(ind),valu);if(ed>mid) updata(st,ed,RR(ind),valu);}up(ind);}}seg;int main(){while(scanf("%d",&n)!=EOF){y.clear(); H.clear(); line.clear();int x1,y1,x2,y2;for(int i=0;i<n;i++){scanf("%d%d%d%d",&x1,&y1,&x2,&y2);line.push_back(Line(x1,y1,y2,1));line.push_back(Line(x2,y1,y2,-1));y.push_back(y1); y.push_back(y2);}sort(line.begin(),line.end());sort(y.begin(),y.end());y.erase(unique(y.begin(),y.end()),y.end());for(int i=0;i<(int)y.size();i++) H[y[i]]=i;int res=0,len=0;seg.build(0,(int)y.size()-1,1);for(int i=0;i<(int)line.size();i++){if(i!=0) res+=seg.tree[1].cnt*(line[i].x-line[i-1].x)*2;seg.updata(H[line[i].y1],H[line[i].y2],1,line[i].flag);res+=iabs(len-seg.tree[1].len);len=seg.tree[1].len;}printf("%d\n",res);}return 0;}

/*代碼風格更新前*/#include <iostream>#include <cstdio>#include <algorithm>using namespace std;const int N=5005;int y[N*2];struct Line{    int x,y1,y2,co;    void fun(int a,int b,int c,int d){x=a;y1=b;y2=c;co=d;}}line[N*2];struct node{    int left,right,co;    int lf,rf,len,cnt;    bool isl,isr;    int mid(){return left+(right-left)/2;}    void change(int a)    {        co+=a;        if(co==0) {len=0;cnt=0;isl=isr=0;}        else {len=rf-lf;cnt=1;isl=isr=1;}    }};struct Segtree{    node tree[N*8];    void build(int left,int right,int r)    {        tree[r].left=left;  tree[r].right=right;        tree[r].len=tree[r].cnt=0;        tree[r].isl=tree[r].isr=0;        tree[r].lf=y[left]; tree[r].rf=y[right];        if(left+1<right)        {            int mid=tree[r].mid();            build(left,mid,r*2);            build(mid,right,r*2+1);        }    }    void updata(Line e,int r)    {        if(tree[r].left+1==tree[r].right)        {            tree[r].change(e.co);        }        else        {            if(e.y1<tree[r*2].rf) updata(e,r*2);            if(e.y2>tree[r*2+1].lf) updata(e,r*2+1);            tree[r].cnt=tree[r*2].cnt+tree[r*2+1].cnt;            tree[r].len=tree[r*2].len+tree[r*2+1].len;            tree[r].isl=tree[r*2].isl;  tree[r].isr=tree[r*2+1].isr;            if(tree[r*2].isr&&tree[r*2+1].isl) tree[r].cnt--;        }    }}seg;int deal(int);int iabs(int a){return a>0?a:-a;}bool cmp(const Line &e1,const Line &e2){    return e1.x<e2.x;}int main(){    int n,d=0;    scanf("%d",&n);    for(int i=0;i<n;i++)    {        int x1,y1,x2,y2;        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);        line[d].fun(x1,y1,y2,1);  y[d++]=y1;        line[d].fun(x2,y1,y2,-1);  y[d++]=y2;    }    int cnt=deal(d);    seg.build(0,cnt-1,1);    seg.updata(line[0],1);    int ans=seg.tree[1].len;    for(int i=1;i<d;i++)    {        int temp=seg.tree[1].len;        ans+=(2*seg.tree[1].cnt*(line[i].x-line[i-1].x));        seg.updata(line[i],1);        ans+=iabs(temp-seg.tree[1].len);        //printf("x1=%d,x2=%d,temp=%d,len=%d,ans=%d\n",line[i].x,line[i-1].x,temp,seg.tree[1].len,ans);    }    printf("%d\n",ans);    return 0;}int deal(int n){    sort(y,y+n);    sort(line,line+n,cmp);    int cnt=1;    for(int i=1;i<n;i++)    {        if(y[i]!=y[i-1]) y[cnt++]=y[i];    }    return cnt;}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.