zoukankan      html  css  js  c++  java
  • POJ3695 Rectangles (线段树+扫描线)

    这题用容斥定理做会代码简单不少,但是一个是我数学不好,另一个我感觉这就是个扫描线模板题

    首先也是求面积并,但是本题不是所有的矩形都用得到,我们根据题目的询问来用vis存储用得到的矩形

    注意,因为我们已经离散化了,所以当前的矩形不是原先的矩形排序,而询问的时候是告诉我们原先矩形的位置,所以我们在输入的时候记录一下他的pos

    本题很卡时限,做到以下几点就没问题了

    1.用c++交

    2.最大的N不要设的太大,本题只有20个矩形,以前我们碰到往往是1e5级别的,所以像我第一次就直接开了1e5,我没想到就这点建树的时间就超时了,所以要开30就行

    3.没有必要重复建树,因为这是扫描线,所有矩形都有出边和入边,全部遍历完后,线段树中一定是空的

    4.以上poj就能成功通过,记得用scanf,如果你的做法poj是tle的,去杭电同题交一下,poj的数据被加强过,如果杭电还是tle,并且卡不了常了,应该是做法问题。

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    const int N=30;
    int a[N];
    int n,m;
    vector<double> ys;
    struct s{
        int x;
        int y1;
        int  y2;
        int k; 
        int num;
        bool operator <(const  s &t) const{
          return x<t.x;
        }
    }sg[N*2];
    struct node{
        int l,r;
        int cnt;
        int  len;
    }tr[N*8];
    int find(int  x){
        int pos=lower_bound(ys.begin(),ys.end(),x)-ys.begin()+1;
        return pos;
    }
    void pushup(int u){
        if(tr[u].cnt){
            tr[u].len=ys[tr[u].r]-ys[tr[u].l-1];
        }
        else if(tr[u].l!=tr[u].r)
        tr[u].len=tr[u<<1].len+tr[u<<1|1].len;
        else
        tr[u].len=0; 
        
    }
    void build(int u,int l,int r){
        tr[u].l=l;
        tr[u].r=r;
        if(l!=r){
            int mid=l+r>>1;
            build(u<<1,l,mid);
            build(u<<1|1,mid+1,r);
        }
    }
    void modify(int u,int l,int r,int k){
        if(tr[u].l>=l&&tr[u].r<=r){
            tr[u].cnt+=k;
            pushup(u);
        }
        else{
            int mid=tr[u].l+tr[u].r>>1;
            if(l<=mid)
            modify(u<<1,l,r,k);
            if(r>mid)
            modify(u<<1|1,l,r,k);
            pushup(u);
        }
    }
    int vis[N];
    int main(){
        int T=1;
        int n;
        while(cin>>n>>m){
            if(n==0&&m==0)
            break;
        ys.clear();
        int i;
        int  x1,x2,y1,y2;
        int cnt=1;
        for(i=1;i<=n;i++){
                cin>>x1>>y1>>x2>>y2;
                sg[cnt].x=x1,sg[cnt].y1=y1,sg[cnt].y2=y2,sg[cnt].k=1,sg[cnt].num=i;
                cnt++;
                sg[cnt].x=x2,sg[cnt].y1=y1,sg[cnt].y2=y2,sg[cnt].k=-1,sg[cnt].num=i;
                cnt++;
                ys.push_back(y1);
                ys.push_back(y2); 
        }
        sort(sg+1,sg+1+2*n);
        sort(ys.begin(),ys.end());
        ys.erase(unique(ys.begin(),ys.end()),ys.end());
        build(1,1,ys.size()-1);
        int sign=1;printf("Case %d:
    ",T++);
        for(i=1;i<=m;i++){
            int r;
            memset(vis,0,sizeof vis);
            scanf("%d",&r);
            int j;
            for(j=1;j<=r;j++){
                int x;
                scanf("%d",&x);
                vis[x]=1; 
            }
            int res=0;
            int pre=0;
            for(j=1;j<=2*n;j++){
                if(!vis[sg[j].num])
                continue;
                if(pre){
                    res+=tr[1].len*(sg[j].x-sg[pre].x);
                }
                modify(1,find(sg[j].y1),find(sg[j].y2)-1,sg[j].k);
                pre=j;
            }
        
        printf("Query %d: %d
    ",sign++,res);
        }
        printf("
    ");
        }
    }
    View Code
  • 相关阅读:
    vue+axios拦截器和webapi中读取的实现
    vue+webapi+jwt做token验证时需要注意的一些问题
    vue中引用js文件的方法
    vue+elementui实现表单验证
    vue编程式路由参数的传递
    vue+elementUI实现侧边菜单栏的功能
    vue+webAPI中json相互转换的点滴记录,用于实现按分值的调查问卷功能
    axios中Post请求的两种区别
    vue使用全局变量来定义axios请求地址
    .net Core3.1 webapi前后端一起部署到同一网站遇到的问题
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/12336737.html
Copyright © 2011-2022 走看看