zoukankan      html  css  js  c++  java
  • 【IOI1998】Picture(扫描线+线段树)

    问题来源:IOI1998 D2T1

    题意:就是在一个平面内给出n个矩形,叫你计算将这些矩形合并以后,新图形的周长。

    例如:

    上图是原本的矩形们      ---------->合并后的图形

    解题思路:拿一条扫描线横着扫一次,遇到左边的边就在这条扫描线上+1,遇到右边的边就在这条扫描线上-1,在边被扫到的时候计算一下线上为0的个数即可。

      因为如果只是单纯的For循环累加,时间会爆,所以我们采用线段树来存这条扫描线的状态优化效率即可。然后竖着再做同样的事做一遍。

      时间效率应该是O(kn)(k是常数)。

    附代码:

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<cstring>
      4 #include<string>
      5 #include<algorithm>
      6 #include<cmath>
      7 #define For(i,a,b) for (int i=a; i<=b; i++)
      8 #define Ford(i,a,b) for (int i=a; i>=b; i--)
      9 #define File(fn) freopen(fn".in","r",stdin); freopen(fn".out","w",stdout);
     10 #define mem(qaq,num) memset(qaq,num,sizeof(qaq));
     11 #define ll long long
     12 #define mod 1000000007
     13 #define INF 2000000000
     14 #define mid ((l+r)>>1)
     15 using namespace std;
     16 struct zxy{
     17     int mi,n,mark;
     18 }tr[65540];
     19 struct edge{
     20     int l,r,h,typ;
     21 }x[10001],y[10001];
     22 int n,ans,cnt;
     23 inline int in(){
     24     int x=0,f=1;
     25     char ch=getchar();
     26     while (ch<'0'||ch>'9') f=ch=='-'?-1:1,ch=getchar();
     27     while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
     28     return x*f;
     29 }
     30 inline void combine(int k){
     31     if (tr[k<<1].mi==tr[k<<1|1].mi) tr[k].n=tr[k<<1].n+tr[k<<1|1].n,tr[k].mi=tr[k<<1].mi;
     32     else 
     33         if(tr[k<<1].mi<tr[k<<1|1].mi) tr[k].n=tr[k<<1].n,tr[k].mi=tr[k<<1].mi;
     34         else tr[k].n=tr[k<<1|1].n,tr[k].mi=tr[k<<1|1].mi;
     35     return;
     36 }
     37 inline void built(int l,int r,int k){
     38     if (l==r){
     39         tr[k].mi=0;
     40         tr[k].n=1;
     41         tr[k].mark=0;
     42         return;
     43     }
     44     built(l,mid,k<<1);
     45     built(mid+1,r,k<<1|1);
     46     combine(k);
     47     tr[k].mark=0;
     48 }
     49 inline void pushdown(int k){
     50     int ad=tr[k].mark;
     51     tr[k<<1].mark+=ad;
     52     tr[k<<1|1].mark+=ad;
     53     tr[k<<1].mi+=ad;
     54     tr[k<<1|1].mi+=ad;
     55     tr[k].mark=0;
     56     return;
     57 }
     58 inline void update(int l,int r,int a,int b,int k,int ad){
     59     if (l>=a&&b>=r){
     60         tr[k].mark+=ad;
     61         tr[k].mi+=ad;
     62         return;
     63     }
     64     if (tr[k].mark) pushdown(k);
     65     if (a<=mid) update(l,mid,a,b,k<<1,ad);
     66     if (b>mid) update(mid+1,r,a,b,k<<1|1,ad);
     67     combine(k);
     68     return;
     69 }
     70 inline int query(int l,int r,int k,int a,int b){
     71     if (l==a&&r==b){
     72         if (tr[k].mi) return 0;
     73         return tr[k].n;
     74     }
     75     if (tr[k].mark) pushdown(k);
     76     if (b<=mid) return query(l,mid,k<<1,a,b);
     77     if (a>mid) return query(mid+1,r,k<<1|1,a,b);
     78     return query(l,mid,k<<1,a,mid)+query(mid+1,r,k<<1|1,mid+1,b);
     79 }
     80 void init(){
     81     n=in();
     82     For(i,1,n){
     83         int x1=in()+10001,y1=in()+10001,x2=in()+10001,y2=in()+10001;
     84         x[++cnt].l=x1+1,x[cnt].r=x2,x[cnt].h=y1,x[cnt].typ=0;
     85         y[cnt].l=y1+1,y[cnt].r=y2,y[cnt].h=x1,y[cnt].typ=0;
     86         x[++cnt].l=x1+1,x[cnt].r=x2,x[cnt].h=y2,x[cnt].typ=1;
     87         y[cnt].l=y1+1,y[cnt].r=y2,y[cnt].h=x2,y[cnt].typ=1;
     88     }
     89     return;
     90 }
     91 bool cmp(edge a,edge b){
     92     return a.h<b.h||(a.h==b.h&&a.typ<b.typ);
     93 }
     94 void work(){
     95     sort(x+1,x+cnt+1,cmp);
     96     built(1,20001,1);
     97     For(i,1,cnt)
     98         if (!x[i].typ){            
     99             ans+=query(1,20001,1,x[i].l,x[i].r);    
    100             update(1,20001,x[i].l,x[i].r,1,1);
    101         }
    102         else{
    103             update(1,20001,x[i].l,x[i].r,1,-1);
    104             ans+=query(1,20001,1,x[i].l,x[i].r);
    105         }
    106     sort(y+1,y+cnt+1,cmp);
    107     built(1,20001,1);
    108     For(i,1,cnt)
    109         if (!y[i].typ){
    110             ans+=query(1,20001,1,y[i].l,y[i].r);
    111             update(1,20001,y[i].l,y[i].r,1,1);
    112         }
    113         else{
    114             update(1,20001,y[i].l,y[i].r,1,-1);
    115             ans+=query(1,20001,1,y[i].l,y[i].r);
    116         }
    117     return;
    118 }
    119 int main(){
    120     init();
    121     work();
    122     printf("%d",ans);
    123 }

     本文由Melacau编写,Melacau代表M星向您问好,如果您不是在我的博客http://www.cnblogs.com/Melacau上看到本文,请您向我联系,email:13960948839@163.com.

  • 相关阅读:
    腾讯云通信服务端返回签名
    synchronized同步语句块
    synchronized同步方法
    springjdbc的批量操作
    yield方法
    暂停线程
    【jdk源码学习】HashMap
    diamond types are not supported at this language level
    【java基础系列】一、常用命令行
    Socket通信综合示例
  • 原文地址:https://www.cnblogs.com/Melacau/p/Picture.html
Copyright © 2011-2022 走看看