zoukankan      html  css  js  c++  java
  • POJ 3695 Rectangles扫描线

    扫描线

    You are developing a software for painting rectangles on the screen. The software supports drawing several rectangles and filling some of them with a color different from the color of the background. You are to implement an important function. The function answer such queries as what is the colored area if a subset of rectangles on the screen are filled.

    Input
    The input consists of multiple test cases. Each test case starts with a line containing two integers N(1 ≤ N ≤ 20) and M(1 ≤ M ≤ 100000), indicating the number of rectangles on the screen and the number of queries, respectively.
    The i-th line of the following N lines contains four integers X1,Y1,X2,Y2 (0 ≤ X1 < X2 ≤ 1000, 0 ≤ Y1 < Y2 ≤ 1000), which indicate that the lower-left and upper-right coordinates of the i-th rectangle are (X1, Y1) and (X2, Y2). Rectangles are numbered from 1 to N.
    The last M lines of each test case describe M queries. Each query starts with a integer R(1<=R ≤ N), which is the number of rectangles the query is supposed to fill. The following list of R integers in the same line gives the rectangles the query is supposed to fill, each integer of which will be between 1 and N, inclusive.

    The last test case is followed by a line containing two zeros.

    Output
    For each test case, print a line containing the test case number( beginning with 1).
    For each query in the input, print a line containing the query number (beginning with 1) followed by the corresponding answer for the query. Print a blank line after the output for each test case.

    Sample Input
    2 2
    0 0 2 2
    1 1 3 3
    1 1
    2 1 2
    2 1
    0 1 1 2
    2 1 3 2
    2 1 2
    0 0
    Sample Output
    Case 1:
    Query 1: 4
    Query 2: 7

    Case 2:
    Query 1: 2

    题意:

    输入n 个矩形,m 次询问,下面 n 行输入矩形的左下角和右上角坐标 ,下面m 次询问,每次第一个数 k 表示后面跟 k 个数,询问 这 k 个矩形的合并面积。

    思路:

    每次询问都对这 k 个矩形做一次标记,开始计算覆盖面积,只不过不用线段树。
    对着 k 个矩形按照 纵坐标 y 从小到大排序,,离散化这些矩形的横坐标 , 然后对于遍历横坐标,同时寻找每两个横坐标之间的最大最小值(连续的 ,对于非连续的直接把之前的U D计算相加)最后计算这一块矩形的面积。
    还是跟切割矩形差不多
    撸代码:

    #include<algorithm>
    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    using namespace std;
    struct node
    {

        int x1,x2,y1,y2;
        int l;
    } p[30],q[50];
    bool comp(node a,node b)
    {
        return a.y1<b.y1;
    }
    int book[30],x[1010];
    int work(int n)
    {
        int cnt=0;
        for(int i=1; i<=n; i++)
        {
            q[i]=p[book[i]];
            x[cnt++]=p[book[i]].x1;
            x[cnt++]=p[book[i]].x2;
        }
        sort(x,x+cnt);
        sort(q+1,q+n+1,comp);
        int m=1;
        /**离散化处理*/
        for(int i=1; i<cnt; i++)
        {
            if(x[i]!=x[i-1])
                x[m++]=x[i];
        }

        int L,R,sum=0,U,D,INF=0x3f3f3f3f;/**U D 计算最大最小值*/
        for(int i=1; i<m; i++)
        {
            L=x[i-1],R=x[i];
            U=0,D=INF;
            for(int j=1; j<=n; j++)
            {
                if(q[j].x1<=L&&q[j].x2>=R)
                {
                    if(q[j].y1>U&&U>D)/**有断层的直接先把之前的加上,换U ,D*/
                    {
                        sum+=(R-L)*(U-D);
                        U=q[j].y2,D=q[j].y1;
                    }
                    else
                    {
                        U=max(U,q[j].y2);
                        D=min(D,q[j].y1);
                    }
                }
            }
            if(U>D)
            {
                sum+=(R-L)*(U-D);
            }
        }

        return sum;
    }
    int main()
    {
        int n,m;
        int t=1;
        while(~scanf("%d%d",&n,&m))
        {
            if(n==0&&m==0)
                break;
            for(int i=1; i<=n; i++)
                scanf("%d%d%d%d",&p[i].x1,&p[i].y1,&p[i].x2,&p[i].y2);
            printf("Case %d: ",t++);
            for(int i=1,k,x; i<=m; i++)
            {
                scanf("%d",&k);
                memset(book,0,sizeof(book));
                for(int j=1; j<=k; j++)
                {
                    scanf("%d",&book[j]);
                }
                printf("Query %d: %d ",i,work(k));
            }
            printf(" ");
        }
        return 0;
    }
  • 相关阅读:
    android 中文 api (43) —— Chronometer
    SVN客户端清除密码
    Android 中文 API (35) —— ImageSwitcher
    Android 中文API (46) —— SimpleAdapter
    Android 中文 API (28) —— CheckedTextView
    Android 中文 API (36) —— Toast
    Android 中文 API (29) —— CompoundButton
    android 中文 API (41) —— RatingBar.OnRatingBarChangeListener
    Android 中文 API (30) —— CompoundButton.OnCheckedChangeListener
    Android 中文 API (24) —— MultiAutoCompleteTextView.CommaTokenizer
  • 原文地址:https://www.cnblogs.com/HappyKnockOnCode/p/12739574.html
Copyright © 2011-2022 走看看