zoukankan      html  css  js  c++  java
  • 扫描线

      这个扫描线气死我了,我理解其中思想 却不知道怎么写

    彻底被结构体优先队列搞疯,以前以为在结构体里面重载运算符就是优先队列结构体,发现错误的照样sort。

    我去,这是真的难受 无奈之下写了一个pair套pair再套pair还套pair

    这可是要exs我了,想define F->first 发现不行鬼畜的first 和second 然后 码长很长。

    晕死了,然后蜜汁离散化 然后蜜汁 优先队列。

    在计算代价的时候GG了发现错了。然后 0分。

    发现是不会扫描线的缘故,恶补扫描线。

    花费了我3h也不知道怎么写扫描线,为什么要离散 怎么搞向上延伸的最大距离。

    不会。。。

    针对这道题 题目大意是求各个矩形面积的并。

    我想我 可以 看书。然后不太会。

    学了至少3h 我也不知道为什么可能中间思考了一些关于线段树的细节的问题。

    这道题考虑将其一块一块分解 求面积 首先我们只要 用|x||y|就能求出每一块矩形。

    然后考虑怎么维护x或者y 让x单调 将y放入线段树中 因为y是一个小数所以 考虑离散

    经过多年离散发现 并不是所有的离散都是那三行离散化。

    求出线每次扫描到的地方即可。

     //#include<bits/stdc++.h>
    #include<iostream>
    #include<cstdio>
    #include<iomanip>
    #include<cstring>
    #include<string>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    #include<cctype>
    #include<utility>
    #include<set>
    #include<bitset>
    #include<queue>
    #include<stack>
    #include<deque>
    #include<map>
    #include<vector>
    #include<ctime>
    #define INF 2147483646
    #define l(x) s[x].l
    #define r(x) s[x].r
    #define c(x) s[x].cnt
    #define sum(x) s[x].len
    using namespace std;
    char buf[1<<15],*fs,*ft;
    inline char getc()
    {
        return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
    }
    inline long long read()
    {
        long long x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    inline void put(long long x)
    {
        x<0?putchar('-'),x=-x:0;
        long long num=0;char ch[50];
        while(x)ch[++num]=x%10+'0',x/=10;
        num==0?putchar('0'):0;
        while(num)putchar(ch[num--]);
        putchar('
    ');return;
    }
    const int MAXN=1000;
    int n,m,num;
    double real[MAXN];//r存y的真实值 v存y的离散值
    struct wy
    {
        double x,y,z;
        int k;
        bool operator <(const wy &h)const 
        {
            return x<h.x;
        }
    }a[MAXN];
    map<double,int>v;
    struct wy1
    {
        int l,r;
        int cnt;
        double len;
    }s[MAXN];
    void build(int p,int l,int r)
    {
        l(p)=l;r(p)=r;
        sum(p)=0;c(p)=0;
        if(l==r)return;
        int mid=(l+r)>>1;
        build(p<<1,l,mid);
        build(p<<1|1,mid+1,r);
    }
    void change(int p,int l,int r,int d)
    {
        if(l<=l(p)&&r>=r(p))sum(p)=((c(p)+=d)?real[r(p)+1]-real[l(p)]:0);
        if(l(p)==r(p))return;
        int mid=(l(p)+r(p))>>1;
        if(l<=mid)change(p<<1,l,r,d);
        if(r>mid)change(p<<1|1,l,r,d);
        sum(p)=(c(p)?real[r(p)+1]-real[l(p)]:sum(p<<1)+sum(p<<1|1));
    }
    
    int main()
    {
        //freopen("1.in","r",stdin);
        while(1)
        {
            n=read();
            if(n==0)break;
            for(int i=1;i<=n;i++)
            {
                int k=i<<1;
                double y,z;
                scanf("%lf %lf %lf %lf",&a[k-1].x,&y,&a[k].x,&z);
                real[k-1]=a[k-1].y=a[k].y=y;//先搞一波y值
                real[k]=a[k-1].z=a[k].z=z;
                a[k-1].k=1;
                a[k].k=-1;
            }
            n=n<<1;
            sort(real+1,real+1+n);
            m=unique(real+1,real+1+n)-(real+1);//离散 建一棵线段树
            for(int i=1;i<=m;i++)v[real[i]]=i;
            sort(a+1,a+1+n);//按照x从小到大排序
            double ans=0;
            build(1,1,m-1);//发现线段树存某个点的cnt没有任何意义 
            //应该存一段区间的值 那么我们建m-1个区间即可
            for(int i=1;i<n;i++)
            {
                int y=v[a[i].y],z=v[a[i].z]-1;
                //cout<<y<<' '<<z<<endl;
                change(1,y,z,a[i].k);
                ans+=sum(1)*(a[i+1].x-a[i].x);
                //cout<<sum(1)<<endl;
            }
            printf("Test case #%d
    ",++num);
            printf("Total explored area: %.2lf
    ",ans);
            puts("");
        }
        return 0;
    }
    View Code

    这道题就是我开头吐槽的那道困扰我好久的题目。很气。

    学过扫描线了 然后发现这题并非是线段树 或者说线段树非常难写。

    点开的题解中发现一篇非常简单体现了扫描线的思路(当然和我想的差不多喽)

    差的是对STL multiset 的使用罢了。

    这里使用multiset维护整个扫描线。然后一条一条加即可完成操作!

    非常巧妙的思想!

     //#include<bits/stdc++.h>
    #include<iostream>
    #include<cstdio>
    #include<iomanip>
    #include<cstring>
    #include<string>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    #include<cctype>
    #include<utility>
    #include<set>
    #include<bitset>
    #include<queue>
    #include<stack>
    #include<deque>
    #include<map>
    #include<vector>
    #include<ctime>
    #define INF 2147483646
    #define h(p) t[p].h
    #define l(p) t[p].x
    #define k(p) t[p].k
    using namespace std;
    char buf[1<<15],*fs,*ft;
    inline char getc()
    {
        return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
    }
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    inline void put(int x)
    {
        x<0?putchar('-'),x=-x:0;
        int num=0;char ch[50];
        while(x)ch[++num]=x%10+'0',x/=10;
        num==0?putchar('0'):0;
        while(num)putchar(ch[num--]);
        putchar(' ');return;
    }
    const int MAXN=100002;
    int x[MAXN<<2],y[MAXN<<2];
    int n,m,cnt;
    struct wy
    {
        int h,x,k;
    }t[MAXN<<1];
    multiset<int>q;
    int cmp(wy x,wy y)
    {
        if(x.x!=y.x)return x.x<y.x;
        if(x.k!=y.k)return x.k<y.k;
        if(x.k==1)return x.h>y.h;
        return x.h<y.h;
    }
    int main()
    {
        //freopen("1.in","r",stdin);
        n=read();
        for(int i=1;i<=n;i++)
        {
            int high,xx,yy;
            high=read();xx=read();yy=read();
            ++m,l(m)=xx,h(m)=high,k(m)=1;
            ++m,l(m)=yy,h(m)=high,k(m)=2;
        }
        sort(t+1,t+1+m,cmp);
        q.insert(0);
        for(int i=1;i<=m;i++)
        {
            int mx=*q.rbegin();
            if(k(i)==1)
            {
                if(h(i)>mx)
                {
                    ++cnt;x[cnt]=l(i);y[cnt]=mx;
                    ++cnt;x[cnt]=l(i);y[cnt]=h(i);
                    q.insert(h(i));
                }
                else q.insert(h(i));
            }
            if(k(i)==2)
            {
                if(h(i)==mx&&q.count(mx)==1)
                {
                    q.erase(mx);
                    ++cnt;x[cnt]=l(i);y[cnt]=mx;
                    ++cnt;x[cnt]=l(i);y[cnt]=*q.rbegin();
                }
                else q.erase(q.find(h(i)));
            }
        }
        put(cnt);puts("");
        for(int i=1;i<=cnt;i++)put(x[i]),put(y[i]),puts("");
        return 0;
    }
    View Code

    既见君子,云胡不喜!

  • 相关阅读:
    品尝阿里云容器服务:负载均衡与容器的关系
    基于微服务架构、运行于容器中的.NET Core示例应用eShopOnContainers
    基于VS2017的Docker Support体检ASP.NET Core站点的Docker部署
    用工厂模式解决ASP.NET Core中依赖注入的一个烦恼
    终于知道什么情况下需要实现.NET Core中的IOptions接口
    ASP.NET Core Web API处理HttpResponseMessage类型返回值的问题
    ASP.NET Core奇遇记:无用户访问,CPU却一直100%
    省一行是一行:在if语句中使用C# 7.0的模式匹配
    ASP.NET Core 2.0 Preview 1 中贴心的新特性
    .NET Core类库项目中如何读取appsettings.json中的配置
  • 原文地址:https://www.cnblogs.com/chdy/p/10415142.html
Copyright © 2011-2022 走看看