zoukankan      html  css  js  c++  java
  • [12.19模拟赛]矩形|扫描线+set

    这可能是道COCI题

    题目大意:

    在二维平面坐标系,依次给出N个矩形。第i个矩形是“差的”,当且仅当:存在一个$j$,满足$i < j le n$,且矩形i和矩形j有重叠面积。

    $1 le N le100000$,坐标范围$[0,10^9]$

    (时限$5s$,空限$512MB$)

    其实一开始就想到是扫描线的,然后不知道如何维护一些奇奇怪怪的东西。直到考完后经人提醒才想起可以用个set来维护,STL是个好东西。

     进入正题:

    • 前置知识:扫描线 (不会的可出门左转度娘

    由题意,我们自然联想到维护每个线段树每个节点所代表的区间中,可以完全覆盖这个区间的矩形里,矩形编号的最大值与不是坏矩形的编号(好像就是最小值。

    显然,我们要支持撤销操作,由此我们想到可以用set来维护上述东西。

    至于维护答案,我们可以在对线段树进行操作时,同步进行。只要把当前节点我们记录的“不是坏矩形的编号”与当前操作所属的矩形的编号作比较就行了。

    这样就可以了吗?

    显然不是。

    容易发现,上述维护方式是错的。至于反例,可以简单得出,这里就不讲了。

    事实上,我们还要多维护一个东西,就是非完全覆盖这个区间的矩形的编号。我们有三类更新答案的操作:

    A.这个矩形把当前节点所表示区间全覆盖了,会对完全覆盖这个区间和非完全覆盖这个区间的矩形都会造成影响。

    (对于完全覆盖这个区间的,我们只需用上前面维护那俩东西,对于非完全覆盖的,我们可以扫描一下set)

    B.这个矩形把没有当前节点所表示区间完全覆盖,至少会对完全覆盖这个区间的矩形造成影响。

    至此,完结撒花~

    附代码:

    #include<bits/stdc++.h>
    using namespace std;
    int x,y,h,w,n,p,tree[4000000],trees[4000000];
    bool bad[1000002];
    int yy[2000002],n_y,ny[2000002],nny;
    set<int> treen[4000000];
    set<int> treem[4000000];
    struct data
    {
        int x,yy1,yy2,num,pp;
    }line[2000002];
    void lisanhua()
    {
        sort(yy+1,yy+1+n_y);
        for (int i=1;i<=n_y;i++)
            if (yy[i]!=yy[i-1])
                ny[++nny]=yy[i];
    }
    bool cmp(data x,data y)
    {
        return (x.x<y.x)||(x.x==y.x&&x.pp<y.pp);
    }
    void maketree(int x,int l,int r)
    {
        if (l==r) 
        {
            tree[x]=0;trees[x]=0;
            return ;
        }
        int mid=(l+r)/2;
        maketree(x*2,l,mid);maketree(x*2+1,mid+1,r);
        tree[x]=0;trees[x]=0;
    }
    void add(int x,int l,int r,int ql,int qr,int k,int num)
    {
        if (trees[x])
        {
            if (num>trees[x]) {bad[trees[x]]=1,trees[x]=0;}
            else if (num<trees[x]) {bad[num]=1;}
        }
        if (l>=ql&&r<=qr) 
        {
            if (k==1) treen[x].insert(num);
            if (k==-1) 
            {
              if (trees[x]==num) trees[x]=0;
              treen[x].erase(num);
             
            } set<int>::iterator it;
              it=treem[x].begin();
              if (treem[x].begin()!=treem[x].end())
              while (1)
              {
                   if (num>*it) {bad[*it]=1;}
                  else if (num<*it) {bad[num]=1;}
                   if (it==(--treem[x].end())) break;
                   it++;
              }
            if (!(treen[x].empty())) tree[x]=*(--treen[x].end());
            if (!bad[num]&&k==1) trees[x]=num;
            return ;
        }
        else
        {
            if (k==1) treem[x].insert(num);
            if (k==-1) {treem[x].erase(num);}
            set<int>::iterator it;
            it=treen[x].begin();
            if (treen[x].begin()!=treen[x].end())
            while (1)
            {
                  if (num>*it) {bad[*it]=1;}
                else if (num<*it) {bad[num]=1;}
                  if (it==(--treen[x].end())) break;
               it++;
            }
        }
        int mid=(l+r)/2;
        if (ql>mid) add(x*2+1,mid+1,r,ql,qr,k,num);
        else if (qr<=mid) add(x*2,l,mid,ql,qr,k,num);
        else
        {
            add(x*2,l,mid,ql,mid,k,num);
            add(x*2+1,mid+1,r,mid+1,qr,k,num);
        }
    }
    int main()
    {
        freopen("2737.in","r",stdin);
        freopen("2737.out","w",stdout);
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            cin>>x>>y>>w>>h;
            int xx1=x+w,yy1=y+h;
            line[++p].x=x;line[p].yy1=y;line[p].yy2=yy1;line[p].num=i;line[p].pp=1;
            line[++p].x=xx1;line[p].yy1=y;line[p].yy2=yy1;line[p].num=i;line[p].pp=-1;
            yy[++n_y]=y;yy[++n_y]=yy1;    
        }
        yy[0]=-1;
        lisanhua();
        sort(line+1,line+1+p,cmp);    
        maketree(1,1,nny);
        for (int i=1;i<=p;i++)
        {
            int np1=lower_bound(ny+1,ny+nny+1,line[i].yy1)-ny,np2=lower_bound(ny+1,ny+nny+1,line[i].yy2)-ny;
            add(1,1,nny,np1,np2-1,line[i].pp,line[i].num);
        }
        for (int i=1;i<=n;i++)
        {
            if (bad[i]) cout<<"NE
    ";else cout<<"DA
    ";
        }
        return 0;
    }
  • 相关阅读:
    第15章 在应用程序中使用虚拟内存(1)
    第14章 探索虚拟内存(2)
    第14章 探索虚拟内存(1)
    第13章 Windows内存体系结构
    第12章 纤程(Fiber)
    第11章 Windows线程池(3)_私有的线程池
    第11章 Windows线程池(2)_Win2008及以上的新线程池
    第11章 Windows线程池(1)_传统的Windows线程池
    第10章 同步设备I/O和异步设备I/O(4)_利用I/O完成端口实现Socket通信
    php+JQuery+Ajax简单实现页面异步刷新 (转)
  • 原文地址:https://www.cnblogs.com/fmj123/p/10176733.html
Copyright © 2011-2022 走看看