zoukankan      html  css  js  c++  java
  • hdu4419 Colourful Rectangle 12年杭州网络赛 扫描线+线段树

    题意:给定n个矩形,每个矩形有一种颜色,RGB中的一种。相交的部分可能为RG,RB,GB,RGB,问这n个矩形覆盖的面积中,7种颜色的面积分别为多少

    思路:把x轴离散化做扫描线,线段树维护一个扫描区间竖直方向上的各种颜色的长度

    刚开始想着直接维护每段区间上7种颜色的长,但是写到删除的时候发现没办法删除,

    然后想了半天,发现:需要的只是整个区间的颜色长度信息,所以,对于颜色更新来说,不需要往下传标记,只需要维护上push_up就好了

    所以添加删除就简单多了。

    用 1 2 4 分别代表R G B 然后RG RB GB RGB 分别为3 5 6 7

    没有颜色用0来表示

    线段树每个节点记录下R,G,B 分别被覆盖了几次。

    往上更新的时候只需要考虑左右儿子的线段覆盖了父亲的颜色后总的区间各个颜色长度为多少即可,注意单个长度的情况。

    一直卡在64位类型的转化上,全都换成64位的不对,最后强制转化才对的。。

    // 略长,但是比较可看,
    /// R:1  G:2  B:4
    int hash[256];
    struct scanline
    {
      int x,y1,y2;
      int col;
      int flag ;
      void set(int _x,int _y1,int _y2,int _col ,int _flag)
      {
        x = _x ;
        y1 = _y1 ;
        y2 = _y2 ;
        col = _col ;
        flag = _flag ;
      }
    };
    bool cmp(scanline t1, scanline t2)
    {
      if(t1.x != t2.x)return t1.x < t2.x;
      return t1.flag > t2.flag;
    }
    scanline sc[maxn * 3];
    int y[maxn * 3 ];
    int num;
    struct node
    {
      int l,r;
      int ml,mr;
      int c1,c2,c4;
      int l1[8];
      int mid()
      {
        return (l + r) /2;
      }
      int len()
      {
        return mr - ml;
      }
    };
    long long area[10];
    node tt[maxn * 3 * 3 ];
    int nn ;
    void init(int root )
    {
      memset(tt[root].l1,0,sizeof(tt[root].l1));
      tt[root].c1 =  tt[root].c2 = tt[root].c4 = 0 ;
    }
    void update1(int root )
    {
     // printf("root = %d
    ",root);
      int col = 0 ;
      if(tt[root].c1 > 0 ) col = col|1;
      if(tt[root].c2 > 0 ) col = col|2;
      if(tt[root].c4 > 0 ) col = col|4;
      //printf("update1: col = %d
    ",col);
        memset(tt[root].l1,0,sizeof(tt[root].l1));
      if(tt[root].r - tt[root].l == 1 )
      {
        tt[root].l1[col] = tt[root].len();
      }
      else if(col == 0 )
      {
        for(int i = 0 ;i < 8 ;i ++ )
          tt[root].l1[i] = tt[root*2].l1[i] + tt[root*2+1].l1[i];
      }
      else if(col != 0 )
      {
        for(int i = 0; i < 8; i ++ )
          tt[root].l1[i|col] += (tt[root*2].l1[i] + tt[root*2+1].l1[i]);
      }
    
      return ;
    }
    void build(int root ,int l,int r )
    {
      tt[root].l = l ;
      tt[root].r = r;
      tt[root].ml = y[l-1];
      tt[root].mr = y[r-1];
      init(root);
      tt[root].l1[0] = tt[root].len();
      if( l + 1 >= r ) return ;
      int mid = tt[root].mid();
      build(root * 2 , l , mid );
      build(root * 2 + 1 , mid , r);
      return ;
    }
    void upd(int root ,int l,int r ,int col,int val )
    {
      if(l <= tt[root].ml && tt[root].mr <= r)
      {
        if(col == 1 ) tt[root].c1 += val ;
        else if(col == 2 ) tt[root].c2 += val ;
        else if(col == 4 ) tt[root].c4 += val ;
        update1(root);
        return ;
      }
      if(r <= tt[root * 2 ].mr )
        upd(root * 2 , l,r,col,val);
      else if(l >= tt[root * 2 + 1].ml )
        upd(root * 2 + 1, l,r ,col,val);
      else
      {
        upd(root * 2 ,l,r,col,val);
        upd(root * 2 + 1 ,l,r,col,val);
      }
      update1(root);
    }
    int main()
    {
      int x1,x2,y1,y2;
      memset(hash,0,sizeof(hash));
      hash['R'] = 1 ;
      hash['G'] = 2 ;
      hash['B'] = 4 ;
      int cas,ccc;
      ccc = 0;
      char str[5];
      scanf("%d",&cas);
      int n ;
      while(cas -- )
      {
        num = 0 ;
        scanf("%d",&n);
        for(int i = 1 ; i <= n ; i++ )
        {
          scanf("%s %d %d %d %d",str,&x1,&y1,&x2,&y2);
          y[num] = y1 ;
          num ++ ;
          sc[num].set(x1,y1,y2,hash[str[0]],1);
    
          y[num] = y2 ;
          num ++ ;
          sc[num].set(x2,y1,y2,hash[str[0]],-1);
        }
        int n1;
        n1 = num ;
        sort(y ,y + num);
        nn = unique(y , y + num) - y;
        build(1,1,nn);
        sort(sc + 1 , sc + n1 + 1,cmp);
        memset(area,0,sizeof(area));
        int i ;
        i = 1 ;
        while(i <= n1 )
        {
          int j = i ;
          while(sc[j].x == sc[i].x && j <= n1 )
          {
            upd(1,sc[j].y1,sc[j].y2,sc[j].col,sc[j].flag);
            j ++ ;
          }
          int len ;
          if(j == n1 + 1 ) len = 0 ;
          else len = sc[j].x - sc[i].x;
          update1(1);
          for(int k = 1 ; k < 8 ; k ++ )
            area[k] = area[k] + (long long)(tt[1].l1[k]) * (long long)(len) ;
          i = j ;
        }
        printf("Case %d:
    ",++ccc);
        printf("%I64d
    %I64d
    %I64d
    %I64d
    %I64d
    %I64d
    %I64d
    ",area[1],area[2],area[4],area[3],area[5],area[6],area[7]);
        ///cout<<area[1]<<endl<<area[2]<<endl<<area[4]<<endl<<area[3]<<endl<<area[5]<<endl<<area[6]<<endl<<area[7]<<endl;
      }
      return 0 ;
    }
    hdu4419
  • 相关阅读:
    Java并发教程(Oracle官方资料)
    java中的字符集和编码
    一篇文章看懂Java并发和线程安全
    mysql中,如何查看数据库中当前可用的校勘?字符集默认的collation?
    mysql数据库中,查看当前支持的字符集有哪些?字符集默认的collation的名字?
    mysql数据库中,通过一条insert into语句,同时插入多个值
    jenkins第一次登陆,输入完密码之后,卡在了SetupWizard[jenkins]处
    mysql数据库,如何在登录mysql之后执行操作系统上的SQL脚本?
    mysql在命令行中,指定要连接的数据库?
    mysql中如何在命令行中,执行一个SQL脚本文件?
  • 原文地址:https://www.cnblogs.com/jh818012/p/3273372.html
Copyright © 2011-2022 走看看