其他分享
首页 > 其他分享> > [扫描线][差分约束] Jzoj P4238 纪念碑

[扫描线][差分约束] Jzoj P4238 纪念碑

作者:互联网

Description

2034年,纪念中学决定修建校庆100周年纪念碑,作为杰出校友的你被找了过来,帮校方确定纪念碑的选址.
纪念中学的土地可以看作是一个长为n,宽为m的矩形.它由n* m个1*1的正方形组成,其中左下角的正方形的坐标为(1,1),右上角的正方形的坐标为(n, m).其中有一些土地已经被用来修建建筑物,每一幢建筑物都可以看做是一个左下角为(x1,y1),右上角为(x2,y2)的矩形.
纪念碑可以看作是一个正方形.校方希望你找出一块最大的正方形区域供他们参考.
 

Input

每一组数据的第一行包含三个整数n,m和p,分别表示学校的长,宽以及建筑物的数量.
接下来的p行,每行包含四个整数x1,y1,x2,y2,分别表示每一幢建筑物左下角以及右上角的坐标.

Output

输出一个数,表示可能的最大边长.
 

Sample Input

13 5 8
8 4 10 4
4 3 4 4
10 2 12 2
8 2 8 4
2 4 6 4
10 3 10 4
12 3 12 4
2 2 4 2

Sample Output

3
 

Data Constraint

对于30%的数据,p<=1000.
对于70%的数据,p<=30000.
对于100%的数据,p<=400000,m,n<=1000000.

 

题解

代码

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <vector>
 4 #define N 1000010
 5 using namespace std;
 6 vector<int> P[N],Q[N];
 7 struct Tree {int l,r,x,y,v;}tree[4*N];
 8 int n,m,p,l,r,ans,x1[N],x2[N],y1[N],y2[N],lazy[4*N];
 9 void build(int d,int l,int r)
10 {
11     tree[d].l=l,tree[d].r=r,tree[d].x=tree[d].y=tree[d].v=r-l+1;
12     if (l==r) return;
13     int mid=l+r>>1;
14     build(d*2,l,mid),build(d*2+1,mid+1,r);
15 }
16 void Lazy_down(int d)
17 {
18     if (lazy[d]) 
19     {
20         tree[d].x=tree[d].y=tree[d].v=0;
21         return;
22     }
23     if (tree[d].l==tree[d].r)
24     {
25         tree[d].x=tree[d].y=tree[d].v=1;
26         return;
27     }
28     tree[d].x=tree[d*2].x+(tree[d*2].x==tree[d*2].r-tree[d*2].l+1)*tree[d*2+1].x;
29     tree[d].y=tree[d*2+1].y+(tree[d*2+1].y==tree[d*2+1].r-tree[d*2+1].l+1)*tree[d*2].y;
30     tree[d].v=max(tree[d*2+1].x+tree[d*2].y,max(tree[d*2].v,tree[d*2+1].v));
31 }
32 void change(int d,int l,int r,int L,int R,int k)
33 {
34     if (L<=l&&r<=R) { lazy[d]+=k,Lazy_down(d); return; }
35     int mid=tree[d].l+tree[d].r>>1;
36     if (L<=mid) change(d*2,l,mid,L,R,k); if (mid<R) change(d*2+1,mid+1,r,L,R,k);
37     Lazy_down(d);
38 }
39 int main()
40 {
41     scanf("%d%d%d",&n,&m,&p);
42     for (int i=1;i<=p;i++) scanf("%d%d%d%d",&x1[i],&y1[i],&x2[i],&y2[i]),P[x1[i]].push_back(i),Q[x2[i]].push_back(i);
43     build(1,1,m),l=1,r=1;
44     while (r<=n)
45     {
46         for (int i=0;i<P[r].size();i++) change(1,1,m,y1[P[r][i]],y2[P[r][i]],1);
47         ans=max(ans,min(tree[1].v,r-l+1));
48         while (tree[1].v<r-l+1)
49         {
50             for (int i=0;i<Q[l].size();i++) change(1,1,m,y1[Q[l][i]],y2[Q[l][i]],-1);
51             l++;
52         }    
53         r++;
54     }
55     printf("%d",ans);
56 }

 

标签:右移,P4238,Jzoj,int,线段,tree,变大,正方形,扫描线
来源: https://www.cnblogs.com/Comfortable/p/10335948.html