扫描线与悬线

好像很水....

但我就是想不到QAQ.......

 

 

AC VIJOS 1055 奶牛浴场

  1 #include <cstdio>
  2 #include <fstream>
  3 #include <iostream>
  4  
  5 #include <cstdlib>
  6 #include <cstring>
  7 #include <algorithm>
  8 #include <cmath>
  9  
 10 #include <queue>
 11 #include <vector>
 12 #include <map>
 13 #include <set>
 14 #include <stack>
 15 #include <list>
 16  
 17 typedef unsigned int uint;
 18 typedef long long int ll;
 19 typedef unsigned long long int ull;
 20 typedef double db;
 21  
 22 using namespace std;
 23  
 24 inline int getint()
 25 {
 26     int res=0;
 27     char c=getchar();
 28     bool mi=false;
 29     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
 30     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
 31     return mi ? -res : res;
 32 }
 33 inline ll getll()
 34 {
 35     ll res=0;
 36     char c=getchar();
 37     bool mi=false;
 38     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
 39     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
 40     return mi ? -res : res;
 41 }
 42  
 43 db eps=1e-20;
 44 inline bool feq(db a,db b)
 45 { return fabs(a-b)<eps; }
 46 
 47 template<typename Type>
 48 inline Type avg(const Type a,const Type b)
 49 { return a+((b-a)/2); }
 50 
 51 
 52 //==============================================================================
 53 //==============================================================================
 54 //==============================================================================
 55 //==============================================================================
 56 
 57 
 58 
 59 int xlim,ylim;
 60 int n;
 61 
 62 struct point{ int x,y; point(int x=0,int y=0):x(x),y(y){} };
 63 
 64 bool cmpx(const point&a,const point&b)
 65 { return a.x!=b.x ? a.x<b.x : a.y<b.y; }
 66 bool cmpy(const point&a,const point&b)
 67 { return a.y!=b.y ? a.y<b.y : a.x<b.x; }
 68 
 69 point a[5050];
 70 
 71 int res=0;
 72 
 73 int main()
 74 {
 75     xlim=getint();
 76     ylim=getint();
 77     //Note that top-left point is (0,0).
 78     
 79     n=getint();    
 80     for(int i=0;i<n;i++)
 81     {a[i].x=getint(); a[i].y=getint(); }
 82     
 83     //scanning line algorithm.
 84     stable_sort(a,a+n,cmpy);
 85     
 86     //left to right scanning.
 87     for(int i=0;i<n;i++)
 88     {
 89         int t=0;    //top limit
 90         int b=xlim; //bottom limit
 91         for(int j=1;j<n;j++) //point-defined right limit scan.
 92         if(t<=a[j].x && a[j].x<=b)
 93         {
 94             res=max(res,(a[j].y-a[i].y)*(b-t));
 95             if(a[j].x<a[i].x) t=a[j].x;
 96             else
 97             if(a[j].x>a[i].x) b=a[j].x;
 98             else
 99             { t=b=a[i].x; break; }
100         }
101          res=max(res,(ylim-a[i].y)*(b-t));
102      }
103      //right to left scanning.
104      for(int i=n-1;i>=0;i--)
105      {         
106          int t=0;    //top limit
107          int b=xlim; //bottom limit
108          for(int j=i-1;j>=0;j--) //point-defined left limit scan.
109          if(t<=a[j].x && a[j].x<=b)
110         {
111             res=max(res,(a[i].y-a[j].y)*(b-t));
112             if(a[j].x<a[i].x) t=a[j].x;
113             else
114             if(a[j].x>a[i].x) b=a[j].x;
115             else
116             { t=b=a[i].x; break; }
117         }
118          res=max(res,a[i].y*(b-t));
119      }
120     
121     //top-bottom scannin;
122     if(n>=1)
123     {
124         stable_sort(a,a+n,cmpx);
125         res=max(res,a[0].x*ylim); //first
126         res=max(res,(xlim-a[n-1].x)*ylim); //last
127         for(int i=1;i<n;i++) //between them
128         res=max(res,(a[i].x-a[i-1].x)*ylim);
129     }
130     else res=max(res,xlim*ylim);
131     
132     printf("%d
",res);
133     
134     return 0;
135 }
View Code

扫描线.

扫描的目的是"枚举所有的极大子矩形".详见 IOI2003 王知昆的论文.....

我们枚举确定某些极大子矩形左端界的点,然后从左到右维护这个极大子矩形的上下界.

注意维护的时候要保证所得到的上下界形成的矩形确实是以枚举的点作左端界点.

并且对于每个点,要对题目给出的边界进行特判.

并且还要反方向扫一遍.

并且还要在与扫描线垂直的方向,把所有左/右边界由题目给出边界确定的极大子矩形枚举一遍.

可以证明这样做以后所有的极大子矩形都被枚举掉了....

 

 

 

 

AC VIJOS 1351 棋盘制作

  1 #include <cstdio>
  2 #include <fstream>
  3 #include <iostream>
  4  
  5 #include <cstdlib>
  6 #include <cstring>
  7 #include <algorithm>
  8 #include <cmath>
  9  
 10 #include <queue>
 11 #include <vector>
 12 #include <map>
 13 #include <set>
 14 #include <stack>
 15 #include <list>
 16  
 17 typedef unsigned int uint;
 18 typedef long long int ll;
 19 typedef unsigned long long int ull;
 20 typedef double db;
 21  
 22 using namespace std;
 23  
 24 inline int getint()
 25 {
 26     int res=0;
 27     char c=getchar();
 28     bool mi=false;
 29     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
 30     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
 31     return mi ? -res : res;
 32 }
 33 inline ll getll()
 34 {
 35     ll res=0;
 36     char c=getchar();
 37     bool mi=false;
 38     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
 39     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
 40     return mi ? -res : res;
 41 }
 42  
 43 db eps=1e-20;
 44 inline bool feq(db a,db b)
 45 { return fabs(a-b)<eps; }
 46 
 47 template<typename Type>
 48 inline Type avg(const Type a,const Type b)
 49 { return a+((b-a)/2); }
 50 
 51 
 52 //==============================================================================
 53 //==============================================================================
 54 //==============================================================================
 55 //==============================================================================
 56 
 57 
 58 int n,m;
 59 
 60 int M[2050][2050];
 61 
 62 int lmx[2050][2050];
 63 int rmx[2050][2050];
 64 
 65 int tmx[2050][2050];
 66 
 67 int res1=0,res2=0;
 68 
 69 int main()
 70 {
 71     n=getint();
 72     m=getint();
 73     
 74     for(int i=0;i<n;i++)
 75     for(int j=0;j<m;j++)
 76     M[i][j]=getint();
 77     
 78     for(int i=0;i<n;i++)
 79     {
 80         lmx[i][0]=0;
 81         for(int j=1;j<m;j++)
 82         lmx[i][j]=( M[i][j]!=M[i][j-1] ? lmx[i][j-1]+1 : 0 );
 83         
 84         rmx[i][m-1]=0;
 85         for(int j=m-2;j>=0;j--)
 86         rmx[i][j]=( M[i][j]!=M[i][j+1] ? rmx[i][j+1]+1 : 0 );
 87     }
 88     
 89     for(int j=0;j<m;j++)
 90     {
 91         tmx[0][j]=0;
 92         for(int i=1;i<n;i++)
 93         tmx[i][j]=( M[i][j]!=M[i-1][j] ? tmx[i-1][j]+1 : 0 );
 94     }
 95     
 96     for(int j=0;j<m;j++)
 97     {
 98         int l=lmx[0][j];
 99         int r=rmx[0][j];
100         
101         for(int i=0;i<n;i++)
102         {
103             res1=max(res1,(l+r+1)*(tmx[i][j]+1));
104             int line=min(l+r+1,tmx[i][j]+1);
105             res2=max(res2,line*line);
106             if(i!=n-1 && tmx[i+1][j]!=0)
107             {
108                 l=min(l,lmx[i+1][j]);
109                 r=min(r,rmx[i+1][j]);
110             }
111             else
112             if(i!=n-1)
113             {
114                 l=lmx[i+1][j];
115                 r=rmx[i+1][j];
116             }
117         }
118     }
119 
120     printf("%d
%d
",res2,res1);
121     
122     return 0;
123 }
View Code

悬线法.

枚举每条悬线,找到可以拓展的左右端界然后计算答案更新答案.

左右的可扩展范围可以预处理+递推出来.

预处理出所有点往左往右的可扩展范围.递推的时候根据点的信息,从上到下维护整条悬线的可扩展范围.

悬线的好处就在于,预处理的时候就按照行列把每个点处理成"障碍点"或"非障碍点". 扫描线如果不做预处理,细节上会神坑(大神轻拍).

可以证明所有的极大子矩形都能够由一条悬线扩展而来.

这样我们就根据上面的方法枚举了所有的极大子矩形.

写的时候注意我们枚举的是悬线,因此一但扫到了障碍点要及时将左右端界扩展到最大的可行界.

剩下的就是细节问题.......下标略感混乱.......

 

 

 

AC USACO 2015 Jan. Gold T1 Cow Rectangles

  1 #include <cstdio>
  2 #include <fstream>
  3 #include <iostream>
  4  
  5 #include <cstdlib>
  6 #include <cstring>
  7 #include <algorithm>
  8 #include <cmath>
  9  
 10 #include <queue>
 11 #include <vector>
 12 #include <map>
 13 #include <set>
 14 #include <stack>
 15 #include <list>
 16  
 17 typedef unsigned int uint;
 18 typedef long long int ll;
 19 typedef unsigned long long int ull;
 20 typedef double db;
 21  
 22 using namespace std;
 23  
 24 inline int getint()
 25 {
 26     int res=0;
 27     char c=getchar();
 28     bool mi=false;
 29     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
 30     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
 31     return mi ? -res : res;
 32 }
 33 inline ll getll()
 34 {
 35     ll res=0;
 36     char c=getchar();
 37     bool mi=false;
 38     while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
 39     while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
 40     return mi ? -res : res;
 41 }
 42  
 43 db eps=1e-20;
 44 inline bool feq(db a,db b)
 45 { return fabs(a-b)<eps; }
 46 
 47 template<typename Type>
 48 inline Type avg(const Type a,const Type b)
 49 { return a+((b-a)/2); }
 50 
 51 
 52 //==============================================================================
 53 //==============================================================================
 54 //==============================================================================
 55 //==============================================================================
 56 
 57 
 58 int n;
 59 
 60 int vx[505],xlim;
 61 int vy[505],ylim;
 62 struct point
 63 {
 64     int x,y; char type;
 65     point(int x=-1,int y=-1,char t=' '):x(x),y(y),type(t){}
 66 };
 67 
 68 point a[505];
 69 
 70 bool cmpx(const point&a,const point&b)
 71 { return a.x==b.x ? a.y<b.y : a.x<b.x; }
 72 
 73 int res=0;
 74 int resS=-1;
 75 inline void update(int cnt,int S)
 76 {
 77     if(cnt>=res)
 78     {
 79         if(cnt>res) res=cnt,resS=S;
 80         else resS=min(resS,S);
 81     }
 82 }
 83 
 84 point x[505];
 85 bool able[505];
 86 
 87 int main()
 88 {
 89     freopen("cowrect.in","r",stdin);
 90     freopen("cowrect.out","w",stdout);
 91     
 92     n=getint();
 93     
 94     for(int i=0;i<n;i++)
 95     {
 96         vx[i]=a[i].x=getint();
 97         vy[i]=a[i].y=getint();
 98         char c=getchar();
 99         while(c!='H' && c!='G') c=getchar();
100         a[i].type=c;
101     }
102     
103     stable_sort(vx,vx+n);
104     stable_sort(vy,vy+n);
105     xlim=(int)(unique(vx,vx+n)-vx);
106     ylim=(int)(unique(vy,vy+n)-vy);
107     
108     stable_sort(a,a+n,cmpx);
109     
110     for(int d1=0;d1<ylim;d1++)
111     for(int d2=d1;d2<ylim;d2++)
112     {
113         int l=vy[d1];
114         int r=vy[d2];
115         
116         int t=0;
117         
118         for(int i=0;i<n;i++)
119         if(l<=a[i].y && a[i].y<=r) x[t++]=a[i];
120         x[t++]=point(10000,10000,'G');
121         
122         for(int i=0;i<t;i++) able[i]=true;
123         
124         for(int i=0;i<t;i++)
125         if(x[i].type=='G' || (i!=0 && x[i-1].x==x[i].x && x[i-1].type=='G'))
126         able[i]=false;
127         for(int i=t-1;i>=0;i--)
128         if(x[i].type=='G' || (i!=t-1 && x[i+1].x==x[i].x && x[i+1].type=='G'))
129         able[i]=false;
130         
131         int last=0;
132         while(!able[last] && last<t) last++;
133         if(last!=t)
134         {
135             for(int i=last;i<t;i++)
136             {
137                 if(!able[i])
138                 {
139                     update(i-last,(x[i-1].x-x[last].x)*(r-l));
140                     last=i+1;
141                 }
142             }
143         }
144     }
145     
146     printf("%d
%d
",res,resS);
147     
148     return 0;
149 }
View Code

叫你找出一个覆盖最多"H"点的最小矩形,并且那个矩形不含"G"点.

$O(n^3)$ 算法......扫描线.......

结果在"如何统计点数最多的可行区间"那里卡了好久...

程序里先把点给拿出来...然后在最后放上一个虚节点....然后打上able标记....两个方向都要扫一遍.......

然后预处理好左端界......然后扫一遍作统计获取答案........

是不是很蠢......TAT

 

原文地址:https://www.cnblogs.com/DragoonKiller/p/4420574.html