码迷,mamicode.com
首页 > 其他好文 > 详细

[zroi249]占领地区

时间:2018-08-05 15:54:41      阅读:137      评论:0      收藏:0      [点我收藏+]

标签:连续   通过   scanf   inf   com   左右   width   初中   int   

技术分享图片

这道题做法好像肥肠多。。其实思路也比较简单:

首先通过一个点有两条斜率分别为1和-1的线段,显然同种斜率的线段不会相交我们可以直接算

显然每个点最多被两条线段经过,如果被经过两次的话把重复的减去就好了。

然后假如把其中一种斜率线段排序的话,对于另一种线段,每次会和一段连续的线段有交点

我们二分他会和哪一些在正方形内会有交点的线段的左右端点。

然后。。会wa。。

调了两个小时我发现了一个神奇的事情。。。

技术分享图片

它们没有交点!

这也就像一下初中数学上的应用题,本来能取很多数,但是因为题目要求而只能取整数

所以按奇偶性分类即可

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cstdlib>
 5 #define M 500010
 6 #define ll long long
 7 using namespace std;
 8 int n,m,tot1,tot2;
 9 ll tot,ans;
10 int a[M],b[M];
11 int ji[M],ou[M];
12 bool vis1[M],vis2[M];
13 int find1(int a)
14 {
15     int l=1,r=tot2,ans=tot2;
16     while(l<=r)
17     {
18         int mid=(l+r)/2;
19         if(b[mid]-a>=2) r=mid-1,ans=mid;
20         else l=mid+1;
21     }
22     return ans;
23 }
24 int find2(int a)
25 {
26     int l=1,r=tot2,ans=tot2;
27     while(l<=r)
28     {
29         int mid=(l+r)/2;
30         if(a+b[mid]>=2) r=mid-1,ans=mid;
31         else l=mid+1;
32     }
33     return ans;
34 }
35 int find3(int a)
36 {
37     int l=1,r=tot2,ans=0;
38     while(l<=r)
39     {
40         int mid=(l+r)/2;
41         if(b[mid]-a<=2*n) ans=mid,l=mid+1;
42         else r=mid-1;
43     }
44     return ans;
45 }
46 int find4(int a)
47 {
48     int l=1,r=tot2,ans=0;
49     while(l<=r)
50     {
51         int mid=(l+r)/2;
52         if(a+b[mid]<=2*n) ans=mid,l=mid+1;
53         else r=mid-1;
54     }
55     return ans;
56 }
57 int main()
58 {
59     scanf("%d%d",&n,&m);
60     for(int i=1;i<=m;i++)
61     {
62         int x,y; scanf("%d%d",&x,&y);
63         vis1[y-x+200000]=true;
64         vis2[x+y+200000]=true;
65     }
66     for(int i=0;i<=500000;i++)
67     {
68         if(vis1[i]) a[++tot1]=i-200000;
69         if(vis2[i]) b[++tot2]=i-200000; 
70     }
71     for(int i=1;i<=tot2;i++) ou[i]=ou[i-1]+(b[i]%2==0);
72     for(int i=1;i<=tot2;i++) ji[i]=ji[i-1]+(b[i]%2==1);
73     for(int i=1;i<=tot1;i++)
74     {
75         int l1=find1(a[i]);
76         int l2=find2(a[i]);
77         int r1=find3(a[i]);
78         int r2=find4(a[i]);
79         int res;
80         if((a[i]+200000)%2==0) res=ou[min(r1,r2)]-ou[max(l1,l2)-1];
81         else res=ji[min(r1,r2)]-ji[max(l1,l2)-1];
82         ans+=res;
83     }
84     for(int i=1;i<=tot1;i++) tot+=n-abs(a[i]);
85     for(int i=1;i<=tot2;i++) tot+=n-abs(b[i]-n-1);
86     printf("%lld",(ll)n*n-tot+ans);
87     return 0;
88 }

 

[zroi249]占领地区

标签:连续   通过   scanf   inf   com   左右   width   初中   int   

原文地址:https://www.cnblogs.com/Slrslr/p/9425950.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!