2016-2017 National Taiwan University World Final Team Selection Contest A - Hacker Cups and Balls
题目:
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
3
0 0 5 5
0 5 5 0
0 5 5 0
9
1
0 0 4 3
6
2
0 0 4 3
1 0 3 3
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\n",ans); 107 return 0; 108 }
作者:weeping
出处:www.cnblogs.com/weeping/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。