2016-2017 National Taiwan University World Final Team Selection Contest A

题目:

Dreamoon likes algorithm competitions very much. But when he feels crazy because he cannot figure out any solution for any problem in a competition, he often draws many meaningless straight line segments on his calculation paper.

Dreamoon's calculation paper is special: it can be imagined as the plane with Cartesian coordinate system with range [0, 2000] × [0, 2000] for the coordinates. The grid lines are all lines of the form x = c or y = c for every integer c between 0 and 2000, inclusive. So, the grid contains 2000 × 2000 squares.

Now, Dreamoon wonders how many grid squares are crossed by at least one of the lines he drew. Please help Dreamoon find the answer. Note that, to cross a square, a segment must contain an interior point of the square.

Input

The first line of input contains an integer N denoting the number of lines Dreamoon draw. The i-th line of following N lines contains four integers xi1, yi1, xi2, yi2, denoting that the i-th segment Dreamoon drew is a straight line segment between points (xi1, yi1) and (xi2, yi2).

  • 1 ≤ N ≤ 2 × 103
  • 0 ≤ xi1, yi1, xi2, yi2 ≤ 2 × 103
  • the lengths of all line segments in input are non-zero

Output

Output one integer on a single line: how many grid squares are crossed by at least one of the line segments which Dreamoon drew.

Example

Input
3
0 0 5 5
0 5 5 0
0 5 5 0
Output
9
Input
1
0 0 4 3
Output
6
Input
2
0 0 4 3
1 0 3 3
Output
6

思路:

  二分答案,check时,把小于等于二分值的数标记为0,大于的标记为1。

  然后排序就是区间内的0和1进行排序,用线段树维护区间0的个数的话,排序就是把一段区间置为0或1。

  最后根据center为是不是为0.

  1 #include <bits/stdc++.h>
  2 
  3 using namespace std;
  4 
  5 #define MP make_pair
  6 #define PB push_back
  7 typedef long long LL;
  8 typedef pair<int,int> PII;
  9 const double eps=1e-8;
 10 const double pi=acos(-1.0);
 11 const int K=1e6+7;
 12 const int mod=1e9+7;
 13 
 14 struct node
 15 {
 16     int l,r;
 17 }q[K];
 18 int n,m,a[K],sum[K],ff[K];
 19 void push_down(int o,int l,int r)
 20 {
 21     int mid=l+r>>1;
 22     if(ff[o]&&sum[o])
 23         sum[o<<1]=mid-l+1,sum[o<<1|1]=r-mid;
 24     else if(ff[o])
 25         sum[o<<1]=0,sum[o<<1|1]=0;
 26     if(ff[o])
 27         ff[o<<1]=ff[o<<1|1]=1;
 28     ff[o]=0;
 29 }
 30 void build(int o,int l,int r,int v)
 31 {
 32     ff[o]=0;
 33     if(l==r)
 34     {
 35         if(a[l]<=v) sum[o]=1;
 36         else sum[o]=0;
 37         return ;
 38     }
 39     build(o<<1,l,l+r>>1,v),build(o<<1|1,(l+r)/2+1,r,v);
 40     sum[o]=sum[o<<1]+sum[o<<1|1];
 41 }
 42 void update(int o,int l,int r,int nl,int nr,int x)
 43 {
 44     //if(nl>nr) while(1);
 45     if(l==nl&&r==nr)
 46     {
 47         if(x==0)    sum[o]=r-l+1;
 48         else sum[o]=0;
 49         ff[o]=1;
 50         return ;
 51     }
 52     push_down(o,l,r);
 53     int mid=l+r>>1;
 54     if(nr<=mid) update(o<<1,l,mid,nl,nr,x);
 55     else if(nl>mid) update(o<<1|1,mid+1,r,nl,nr,x);
 56     else update(o<<1,l,mid,nl,mid,x),update(o<<1|1,mid+1,r,mid+1,nr,x);
 57     sum[o]=sum[o<<1]+sum[o<<1|1];
 58 }
 59 int query(int o,int l,int r,int nl,int nr)
 60 {
 61     //if(nl>nr) while(1);
 62     if(l==nl&&r==nr)    return sum[o];
 63     push_down(o,l,r);
 64     int mid=l+r>>1;
 65     if(nr<=mid) return query(o<<1,l,mid,nl,nr);
 66     else if(nl>mid) return query(o<<1|1,mid+1,r,nl,nr);
 67     return query(o<<1,l,mid,nl,mid)+query(o<<1|1,mid+1,r,mid+1,nr);
 68 }
 69 bool check(int x)
 70 {
 71     build(1,1,n,x);
 72     for(int i=1;i<=m;i++)
 73     if(q[i].l<q[i].r)
 74     {
 75         int cnt=query(1,1,n,q[i].l,q[i].r);
 76         if(cnt)
 77             update(1,1,n,q[i].l,q[i].l+cnt-1,0);
 78         if(q[i].l+cnt<=q[i].r)
 79             update(1,1,n,q[i].l+cnt,q[i].r,1);
 80     }
 81     else if(q[i].l>q[i].r)
 82     {
 83         int cnt=q[i].l-q[i].r+1-query(1,1,n,q[i].r,q[i].l);
 84         if(cnt)
 85         update(1,1,n,q[i].r,q[i].r+cnt-1,1);
 86         if(q[i].r+cnt<=q[i].l)
 87             update(1,1,n,q[i].r+cnt,q[i].l,0);
 88     }
 89     return query(1,1,n,(n+1)/2,(n+1)/2)==1;
 90 }
 91 
 92 int main(void)
 93 {
 94     scanf("%d%d",&n,&m);
 95     for(int i=1;i<=n;i++)
 96         scanf("%d",a+i);
 97     for(int i=1;i<=m;i++)
 98         scanf("%d%d",&q[i].l,&q[i].r);
 99     int l=1,r=n,ans=0;
100     while(l<=r)
101     {
102         int mid=l+r>>1;
103         if(check(mid)) r=mid-1,ans=mid;
104         else l=mid+1;
105     }
106     printf("%d
",ans);
107     return 0;
108 }
原文地址:https://www.cnblogs.com/weeping/p/7301623.html