[关闭]
@y20070316 2017-03-01T08:40:45.000000Z 字数 23684 阅读 1020

计算几何

OI



一、半平面交

bzoj2618√
bzoj3190√
bzoj2732
bzoj1038
bzoj1007√
bzoj1137√
bzoj3800

【bzoj3190】【jloi2013】赛车 数形结合+半平面交

分析

按照【bzoj1007】那种用斜率求小于180°的半平面交的方法。
然后把交点的x小于0的部分全都除掉。
注意特判两条线重合的情况。

规则:
①如果露出一个点,那么也要算。
②如果重合,那么也要算。

对此,我们对斜率排序后,保留重合且截距最大的,还有斜率不同的。
判断删除某个半平面的时候,用而不是,确定出
确定的时候,还要避免重合的情况,往后移,然后再往左移。

代码

  1. #include <cstdio>
  2. #include <cctype>
  3. #include <cmath>
  4. #include <algorithm>
  5. using namespace std;
  6. #define F(i,a,b) for (int i=(a);i<=(b);i++)
  7. #define LD long double
  8. const int N=16384;
  9. int n;
  10. struct Line {
  11. int id; LD k,b;
  12. Line(int _id=0,LD _k=0,LD _b=0):id(_id),k(_k),b(_b){}
  13. friend int operator < (Line a,Line b) {
  14. if (a.k!=b.k) return a.k<b.k; else return a.b>b.b;
  15. }
  16. }p[N];
  17. int ID(Line a,Line b) {
  18. return a.id<b.id;
  19. }
  20. Line s[N];
  21. int l,r;
  22. int rd(void) {
  23. int x=0,f=1; char c=getchar();
  24. for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;
  25. for (;isdigit(c);c=getchar()) x=x*10+c-'0';
  26. return x*f;
  27. }
  28. LD inter(Line a,Line b) {
  29. return -(a.b-b.b)/(a.k-b.k);
  30. }
  31. int main(void) {
  32. #ifndef ONLINE_JUDGE
  33. freopen("sdchr.in","r",stdin);
  34. freopen("sdchr.out","w",stdout);
  35. #endif
  36. n=rd(); F(i,1,n) p[i].id=i; F(i,1,n) p[i].b=rd(); F(i,1,n) p[i].k=rd();
  37. sort(p+1,p+n+1);
  38. int t=0;
  39. F(i,1,n) {
  40. Line tmp=p[i];
  41. int j=i;
  42. while (j+1<=n&&p[j+1].k==p[i].k)
  43. j++;
  44. F(k,i,j)
  45. if (p[k].b==tmp.b)
  46. p[++t]=p[k];
  47. i=j;
  48. }
  49. n=t;
  50. F(i,1,n) {
  51. while (r>=2) {
  52. LD x1=inter(p[i],s[r-1]);
  53. LD x2=inter(p[i],s[r]);
  54. if (x1>x2)
  55. s[r--]=Line();
  56. else break;
  57. }
  58. s[++r]=p[i];
  59. }
  60. t=l=1;
  61. while (t+1<=r)
  62. if ((s[t].b==s[t+1].b&&s[t].k==s[t+1].k)||inter(s[t],s[t+1])<0)
  63. t++;
  64. else break;
  65. while (t-1>=l)
  66. if (s[t].b==s[t-1].b&&s[t].k==s[t-1].k)
  67. t--;
  68. else break;
  69. l=t;
  70. printf("%d\n",r-l+1);
  71. sort(s+l,s+r+1,ID);
  72. F(i,l,r-1)
  73. printf("%d ",s[i].id);
  74. printf("%d\n",s[r].id);
  75. return 0;
  76. }

【bzoj2618】【cqoi2618】凸多边形 模板题

代码

  1. #include <cstdio>
  2. #include <cctype>
  3. #include <cmath>
  4. #include <algorithm>
  5. using namespace std;
  6. #define F(i,a,b) for (int i=(a);i<=(b);i++)
  7. #define Vector point
  8. const int M=64;
  9. const int L=512;
  10. int m;
  11. struct point {
  12. double x,y;
  13. point(double _x=0,double _y=0):x(_x),y(_y){}
  14. friend point operator + (point a,point b) {
  15. return point(a.x+b.x,a.y+b.y);
  16. }
  17. friend point operator - (point a,point b) {
  18. return point(a.x-b.x,a.y-b.y);
  19. }
  20. point operator * (double w) {
  21. return point(x*w,y*w);
  22. }
  23. friend double operator ^ (point a,point b) {
  24. return a.x*b.y-a.y*b.x;
  25. }
  26. }p[M];
  27. int n,tot;
  28. struct Line {
  29. point x;
  30. Vector v;
  31. double ang;
  32. Line(point _x=point(),Vector _v=point()):x(_x),v(_v){}
  33. friend int operator < (Line a,Line b) {
  34. if (a.ang!=b.ang)
  35. return a.ang<b.ang;
  36. else return (a.v^(b.x-a.x))<0;
  37. }
  38. void Ang(void) {
  39. ang=atan2(v.y,v.x);
  40. }
  41. }line[L];
  42. Line s[L];
  43. int l,r;
  44. point it[L];
  45. int len;
  46. double ans;
  47. int rd(void) {
  48. int x=0,f=1; char c=getchar();
  49. for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;
  50. for (;isdigit(c);c=getchar()) x=x*10+c-'0';
  51. return x*f;
  52. }
  53. point Inter(Line a,Line b) {
  54. Vector u=a.x-b.x;
  55. double t=(u^b.v)/(b.v^a.v);
  56. return a.x+a.v*t;
  57. }
  58. int on_right(Line a,point p) {
  59. return (a.v^(p-a.x))<=0;
  60. }
  61. void HPI(void) {
  62. sort(line+1,line+tot+1);
  63. int t=0;
  64. F(i,1,tot)
  65. if (line[i].ang!=line[i-1].ang)
  66. line[++t]=line[i];
  67. tot=t;
  68. l=1,r=0;
  69. F(i,1,tot) {
  70. while (l<r&&on_right(line[i],Inter(s[r-1],s[r])))
  71. s[r--]=Line();
  72. while (l<r&&on_right(line[i],Inter(s[l],s[l+1])))
  73. s[l++]=Line();
  74. s[++r]=line[i];
  75. }
  76. while (l<r&&on_right(s[l],Inter(s[r-1],s[r])))
  77. s[r--]=Line();
  78. s[r+1]=s[l];
  79. }
  80. int main(void) {
  81. #ifndef ONLINE_JUDGE
  82. freopen("sdchr.in","r",stdin);
  83. #endif
  84. n=rd();
  85. F(j,1,n) {
  86. m=rd();
  87. F(i,1,m) {
  88. double x=rd(),y=rd();
  89. p[i]=point(x,y);
  90. }
  91. p[m+1]=p[1];
  92. F(i,1,m)
  93. line[++tot]=Line(p[i],p[i+1]-p[i]);
  94. }
  95. F(i,1,tot) line[i].Ang();
  96. HPI();
  97. F(i,l,r)
  98. it[++len]=Inter(s[i],s[i+1]);
  99. F(i,2,len-1)
  100. ans+=fabs(((it[i]-it[1])^(it[i+1]-it[1])))/2.0;
  101. printf("%0.3lf\n",ans);
  102. return 0;
  103. }

【bzoj1007】【hnoi2008】水平相交直线 半平面交

题意

给定若干条直线。
求从无限高的地方看下来,能看见哪些直线。

分析

需要明确这样几个概念:
半平面:一条直线的一侧的所有区域。通过一条有向的直线来刻画,该线段的上方就是半平面,半平面的斜率就是有向线段的斜率。
半平面交:若干个半平面的交集,就是半平面交。

先说明一下这道题与半平面交的关系。
想象一下,从无线高的地方看下来,你会看到一个下凸壳。
这道题相当于求所有朝向为轴正方向的直线的半平面交

我们考虑按照直线的斜率进行从小到大的排序,逐个添加,维护半平面交

如上图所示,其中为蓝线与黑线的交点,为蓝线与棕线的交点。
假设当前我们添加了黑线、棕线,现在要添加蓝线。蓝线有三种可能,分别对应图中的三条蓝线。由此可得:当时,我们直接添加蓝线,否则将棕线进行删除。

代码

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. #define F(i,a,b) for (int i=(a);i<=(b);i++)
  4. #define D(i,a,b) for (int i=(a);i>=(b);i--)
  5. #define fore(v,u) for (vector<int>::iterator v=g[u].begin();v!=g[u].end();v++)
  6. #define LL long long
  7. #define LD long double
  8. LL rd(void) {
  9. LL x=0,f=1; char c=getchar();
  10. for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;
  11. for (;isdigit(c);c=getchar()) x=x*10+c-'0';
  12. return x*f;
  13. }
  14. char rdc(void) {
  15. char c=getchar();
  16. while (!isalpha(c))
  17. c=getchar();
  18. return c;
  19. }
  20. const int N=65536;
  21. int n;
  22. struct Line {
  23. int id; double k,b;
  24. Line(int _id=0,double _k=0,double _b=0):id(_id),k(_k),b(_b){}
  25. friend int operator < (Line a,Line b) {
  26. if (a.k!=b.k) return a.k<b.k; else return a.b>b.b;
  27. }
  28. }line[N];
  29. void Init(void) {
  30. n=rd();
  31. F(i,1,n) {
  32. double k=rd(),b=rd();
  33. line[i]=Line(i,k,b);
  34. }
  35. }
  36. Line s[N]; int tot;
  37. double Cross(Line a,Line b) {
  38. //保证a.k!=b.k,返回交点的x坐标
  39. return (a.b-b.b)/(a.k-b.k);
  40. }
  41. int cmp_id(Line a,Line b) {
  42. return a.id<b.id;
  43. }
  44. void Solve(void) {
  45. sort(line+1,line+n+1);
  46. F(i,1,n) {
  47. if (i!=1&&line[i].k==line[i-1].k)
  48. continue;
  49. while (tot>=2) {
  50. double s1=Cross(s[tot],line[i]);
  51. double s2=Cross(s[tot-1],line[i]);
  52. if (s1>=s2)
  53. s[tot--]=Line();
  54. else break;
  55. }
  56. s[++tot]=line[i];
  57. }
  58. sort(s+1,s+tot+1,cmp_id); F(i,1,tot) printf("%d ",s[i].id); printf("\n");
  59. }
  60. int main(void) {
  61. #ifndef ONLINE_JUDGE
  62. freopen("sdchr.in","r",stdin);
  63. #endif
  64. Init();
  65. Solve();
  66. return 0;
  67. }

二、凸包 & 旋转卡壳

bzoj3533√
bzoj1027√
bzoj2961√
bzoj2300√
bzoj1185√
zoj1081√
hdu2108√
bzoj3203√
bzoj1069√

【bzoj3533】【sdoi2014】向量集 线段树+凸包+三分

题意

维护一个向量集合,在线支持以下操作:
"":加入向量;
",其中为已经加入的向量个数)
询问第个到第个加入的向量与向量的点积的最大值。 集合初始时为空。

分析

  首先有这样一个结论:点积最大的向量一定在凸包上。
  直观的理解:点积,对于相同的,则要求上的投影尽可能地大。即要求的方向上走得越远越好,所以必须要在边界上。
  证明:对于点,点积为


所以

对于这条式子的几何解释为:过点的斜率为的直线,其截距为
所以问题相当于对每个点做一条斜率为的直线,当时,使得解决尽可能的大,当时,使得尽可能的小。
我们考虑对向量所在的直线做一条垂直的线段,并从无穷远的地方开始扫描,则扫描到的最后一个节点就是我们所求。所以一定在凸包上。
总之,对于,点一定在上凸壳上,对于,点一定在下凸壳上。

  确定在凸包上了,我们又有了新发现:凸包上的点按照极角序排序,与的点积是单峰的。所以我们假如能求得凸包,那么在凸包上三分即可解决问题。

  至于区间的凸包怎么求。假如能将区间划分成多个子区间,对于每个子区间求凸包进行三分,再取最大值,那么最终求出来的答案亦满足要求。所以考虑使用线段树,每个区间存区间的所有点的凸包。
  确定使用线段树的结构后,考虑怎样构建凸包。最简单的想法是维护一个set,动态维护凸包。但是太麻烦了,由于我们每次在序列末插入一个点,所以考虑如果对于某个区间,插入的是这个区间的最后一个点,再把整个区间的点建立凸包。

  我写的是zkw线段树,稍微会快一些,然后也是因为中大的那些评委们也会卡常的。

代码

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. #define F(i,a,b) for (int i=(a);i<=(b);i++)
  4. #define D(i,a,b) for (int i=(a);i>=(b);i--)
  5. #define fore(v,u) for (vector<int>::iterator v=g[u].begin();v!=g[u].end();v++)
  6. #define LL long long
  7. #define LD long double
  8. const LL MAX=(LL)1e17;
  9. const LL MIN=(LL)-1e17;
  10. LL rd(void) {
  11. LL x=0,f=1; char c=getchar();
  12. for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;
  13. for (;isdigit(c);c=getchar()) x=x*10+c-'0';
  14. return x*f;
  15. }
  16. char rdc(void) {
  17. char c=getchar();
  18. while (!isalpha(c))
  19. c=getchar();
  20. return c;
  21. }
  22. int decode(int x,LL ans) {
  23. return x^(ans&0x7fffffff);
  24. }
  25. struct point {
  26. int x,y;
  27. point(int _x=0,int _y=0):x(_x),y(_y){}
  28. friend LL operator / (point a,point b) {
  29. return (LL)a.x*b.y-(LL)a.y*b.x;
  30. }
  31. friend LL operator * (point a,point b) {
  32. return (LL)a.x*b.x+(LL)a.y*b.y;
  33. }
  34. friend int operator < (point a,point b) {
  35. if (a.x!=b.x) return a.x<b.x; else return a.y<b.y;
  36. }
  37. friend point operator - (point a,point b) {
  38. return point(a.x-b.x,a.y-b.y);
  39. }
  40. };
  41. const int N=1048576;
  42. int n;
  43. int m; int r[N];
  44. vector<point> pt[N],up[N],dw[N];
  45. void Push(int x,int xl,int xr) {
  46. r[x]=xr;
  47. if (x<(1<<m)) {
  48. int mid=(xl+xr)>>1;
  49. Push(x<<1,xl,mid);
  50. Push(x<<1|1,mid+1,xr);
  51. }
  52. }
  53. void Prework(void) {
  54. n=rd();
  55. for (m=1;(1<<m)<=n+1;m++);
  56. Push(1,0,(1<<m)-1);
  57. }
  58. void Flow(int x) {
  59. static point tmp[N]; int n=0; F(i,1,pt[x].size()) tmp[++n]=pt[x][i-1];
  60. sort(tmp+1,tmp+n+1);
  61. static point t2[N]; int tot=0;
  62. F(i,1,n) {
  63. while (tot>=2&&(t2[tot]-t2[tot-1])/(tmp[i]-t2[tot-1])<=0)
  64. t2[tot--]=point();
  65. t2[++tot]=tmp[i];
  66. }
  67. dw[x].resize(tot+1); F(i,1,tot) dw[x][i]=t2[i];
  68. tot=0;
  69. D(i,n,1) {
  70. while (tot>=2&&(t2[tot]-t2[tot-1])/(tmp[i]-t2[tot-1])<=0)
  71. t2[tot--]=point();
  72. t2[++tot]=tmp[i];
  73. }
  74. up[x].resize(tot+1); F(i,1,tot) up[x][i]=t2[i];
  75. }
  76. void Insert(int x,point p) {
  77. for (int now=x+(1<<m);now>0;now>>=1) {
  78. pt[now].push_back(p);
  79. if (r[now]==x)
  80. Flow(now);
  81. }
  82. }
  83. LL Query(vector<point> &vec,int l,int r,point p) {
  84. while (r-l>=3) {
  85. int _l=(l+l+r)/3;
  86. int _r=(l+r+r)/3;
  87. if (p*vec[_l]>p*vec[_r])
  88. r=_r;
  89. else l=_l;
  90. }
  91. LL ans=MIN;
  92. F(i,l,r)
  93. ans=max(ans,p*vec[i]);
  94. return ans;
  95. }
  96. LL Ask(int l,int r,point p) {
  97. LL ans=MIN;
  98. for (l--,r++,l+=(1<<m),r+=(1<<m);l^r^1;l>>=1,r>>=1) {
  99. if (!(l&1)) {
  100. if (p.y>=0) ans=max(ans,Query(up[l^1],1,up[l^1].size()-1,p));
  101. if (p.y<=0) ans=max(ans,Query(dw[l^1],1,dw[l^1].size()-1,p));
  102. }
  103. if (r&1) {
  104. if (p.y>=0) ans=max(ans,Query(up[r^1],1,up[r^1].size()-1,p));
  105. if (p.y<=0) ans=max(ans,Query(dw[r^1],1,dw[r^1].size()-1,p));
  106. }
  107. }
  108. return ans;
  109. }
  110. void Work(void) {
  111. LL ans=0; char c=rdc(); int tot=0;
  112. F(cc,1,n) {
  113. char kd=rdc();
  114. if (kd=='A') {
  115. int x=rd(),y=rd();
  116. if (c!='E')
  117. x=decode(x,ans),y=decode(y,ans);
  118. Insert(++tot,point(x,y));
  119. }
  120. else if (kd=='Q') {
  121. int x=rd(),y=rd(),l=rd(),r=rd();
  122. if (c!='E')
  123. x=decode(x,ans),y=decode(y,ans),l=decode(l,ans),r=decode(r,ans);
  124. ans=Ask(l,r,point(x,y));
  125. printf("%lld\n",ans);
  126. }
  127. }
  128. }
  129. int main(void) {
  130. #ifndef ONLINE_JUDGE
  131. freopen("sdchr.in","r",stdin);
  132. freopen("sdchr.out","w",stdout);
  133. #endif
  134. Prework();
  135. Work();
  136. return 0;
  137. }

【bzoj1027】合金 数形结合+Floyd求最小环

分析

数形结合+计算几何+Floyd最小环。
http://blog.csdn.net/popoqqq/article/details/40539273

代码

  1. #include <cstdio>
  2. #include <climits>
  3. #include <cmath>
  4. #include <algorithm>
  5. using namespace std;
  6. #define rep(i,a,b) for (int i=(a);i<=(b);i++)
  7. const int M=512;
  8. const int N=512;
  9. const int MAX=INT_MAX>>1;
  10. const double EPS=1e-15;
  11. int cmp(double x);
  12. int m,n;
  13. struct point
  14. {
  15. double x,y;
  16. point(double _x=0,double _y=0) {
  17. x=_x,y=_y;
  18. }
  19. friend point operator - (point a,point b) {
  20. return point(a.x-b.x,a.y-b.y);
  21. }
  22. friend point operator * (point a,point b) {
  23. return point(a.x*b.x,a.y*b.y);
  24. }
  25. friend int operator == (point a,point b) {
  26. return !cmp(a.x-b.x)&&!cmp(a.y-b.y);
  27. }
  28. friend int operator != (point a,point b) {
  29. return !(a==b);
  30. }
  31. }mer[M],prd[N];
  32. int f[M][M];
  33. int res;
  34. void Init(void) {
  35. scanf("%d%d",&m,&n);
  36. rep(i,1,m) {
  37. double x,y; scanf("%lf%lf%*lf",&x,&y);
  38. mer[i]=point(x,y);
  39. }
  40. rep(i,1,n) {
  41. double x,y; scanf("%lf%lf%*lf",&x,&y);
  42. prd[i]=point(x,y);
  43. }
  44. }
  45. int cmp(double x)
  46. {
  47. if(fabs(x)<EPS) return 0;
  48. return x>0?1:-1;
  49. }
  50. double det(point a,point b) {
  51. return a.x*b.y-a.y*b.x;
  52. }
  53. int Left(point k,point a,point b) {
  54. double t=det(b-a,k-a);
  55. return t>0;
  56. }
  57. int On(point k,point a,point b) {
  58. if (cmp(det(k-a,b-a))!=0) return 0;
  59. if (!(cmp(min(a.x,b.x)-k.x)<=0&&cmp(k.x-max(a.x,b.x))<=0)) return 0;
  60. if (!(cmp(min(a.y,b.y)-k.y)<=0&&cmp(k.y-max(a.y,b.y))<=0)) return 0;
  61. return 1;
  62. }
  63. /*
  64. bool On(const point &a,const point &b,const point &c) {
  65. return !cmp(det(a-b,c-b))&&cmp((a.x-b.x)*(a.x-c.x))<=0&&cmp((a.y-b.y)*(a.y-c.y))<=0;
  66. }
  67. */
  68. int Check(point a,point b) {
  69. rep(i,1,n) {
  70. int t1=Left(prd[i],a,b);
  71. int t2=On(prd[i],a,b);
  72. if (!t1&&!t2) return 0;
  73. }
  74. return 1;
  75. }
  76. void MakeGraph(void) {
  77. rep(i,1,m) rep(j,1,m) f[i][j]=MAX;
  78. rep(i,1,m) rep(j,1,m)
  79. if (Check(mer[i],mer[j]))
  80. f[i][j]=1;
  81. }
  82. int Floyd(void) {
  83. rep(i,1,m) {
  84. int mrk=1;
  85. rep(j,1,n) if (mer[i]!=prd[j]) {
  86. mrk=0;
  87. break;
  88. }
  89. if (mrk) return 1;
  90. }
  91. rep(i,1,m) rep(j,1,m) {
  92. int mrk=1;
  93. rep(k,1,n)
  94. if (!On(prd[k],mer[i],mer[j])) {
  95. mrk=0;
  96. break;
  97. }
  98. if (mrk) return 2;
  99. }
  100. /*
  101. rep(i,1,m) {
  102. rep(j,1,m)
  103. if (f[i][j]!=MAX)
  104. printf("%d ",f[i][j]);
  105. else printf("0 ");
  106. printf("\n");
  107. }
  108. */
  109. int ans=MAX;
  110. rep(k,1,m) rep(i,1,m) rep(j,1,m)
  111. f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
  112. rep(i,1,m) ans=min(ans,f[i][i]);
  113. return ans!=MAX?ans:-1;
  114. }
  115. int main(void) {
  116. #ifndef ONLINE_JUDGE
  117. freopen("bzoj1027.in","r",stdin);
  118. freopen("bzoj1027.out","w",stdout);
  119. #endif
  120. Init();
  121. MakeGraph();
  122. res=Floyd();
  123. printf("%d\n",res);
  124. return 0;
  125. }

【bzoj2961】共点圆 cdq分治+凸包

题意

      在平面直角坐标系中,Wayne需要你完成次操作,操作只有两种:
:表示在坐标系中加入一个以为圆心且过原点的圆。
:表示询问点是否在所有已加入的圆的内部(含圆周),且至少在一个圆内部(含圆周)。
      为了减少你的工作量,题目保证圆心严格在x轴上方(纵坐标为正),且横坐标非零。
      数据范围:

分析

      我们考虑怎么判定一个点是否在一个以半径为、以为圆心的圆上。
      我们有:


      将①②代入③,化简得到:

      所以,点在过原点的以为圆心的圆上,当且仅当在半平面内。
      假如要判定一个点是否被所有圆覆盖,那么就看它之前的所有圆心是否都在这个点对应的半平面内。
      现在的问题被转化为:
①向平面内加一个点
②给一个半平面,问是否之前添加的所有点都在半平面内
      由于这个问题满足两个性质:①可以离线 ②可以操作间互不影响,所以我们考虑使用按照时间进行分治的方法。
      问题被简化为:给定平面内的一堆点,多次给定一个半平面,问这个半平面是否覆盖所有的点。
      这是一个很简单的问题。如何刻画一个半平面覆盖所有的点?即所有的点都在半平面的上面。我们把半平面用一个向量进行表示,向量的上边表示半平面内,下边表示半平面外。那么,即要求所有点在该向量的逆时针方向,直接使用叉积进行判断就行了。
      但是点太多了,会TLE。考虑优化。影响答案的点一定在凸包=上凸壳+下凸壳上。且凸壳上的点与当前向量构成的叉积是单峰的(单谷的)。考虑在凸包上二分就好了。当然也可以用三分,还有直接按照半平面进行极角排序,然后two pointer扫一遍。
      其实有一种不用cdq分治的想法。直接使用平衡树动态维护凸包就好了。考虑使用set来实现平衡树,其实也很简便。

代码

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. #define F(i,a,b) for (int i=(a);i<=(b);i++)
  4. #define D(i,a,b) for (int i=(a);i>=(b);i--)
  5. #define fore(v,u) for (vector<int>::iterator v=g[u].begin();v!=g[u].end();v++)
  6. #define LL long long
  7. #define LD double
  8. LL rd(void) {
  9. LL x=0,f=1; char c=getchar();
  10. for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;
  11. for (;isdigit(c);c=getchar()) x=x*10+c-'0';
  12. return x*f;
  13. }
  14. char rdc(void) {
  15. char c=getchar();
  16. while (!isalpha(c))
  17. c=getchar();
  18. return c;
  19. }
  20. #define N 524288
  21. struct point {
  22. LD x,y;
  23. point(LD _x=0,LD _y=0):x(_x),y(_y){}
  24. friend point operator - (point a,point b) {
  25. return point(a.x-b.x,a.y-b.y);
  26. }
  27. friend LD operator / (point a,point b) {
  28. return a.x*b.y-a.y*b.x;
  29. }
  30. friend int operator < (point a,point b) {
  31. if (a.x!=b.x) return a.x<b.x; else return a.y<b.y;
  32. }
  33. }org;
  34. int m;
  35. struct OP {
  36. int kd; point p;
  37. OP(int _kd=0,point _p=point()):kd(_kd),p(_p){}
  38. }op[N];
  39. int ans[N],cnt[N];
  40. point p[N]; int n;
  41. point s_dw[N]; int tot_dw;
  42. point s_up[N]; int tot_up;
  43. void Graham(void) {
  44. sort(p+1,p+n+1);
  45. while (tot_dw>0) s_dw[tot_dw--]=point();
  46. F(i,1,n) {
  47. while (tot_dw>=2&&(s_dw[tot_dw]-s_dw[tot_dw-1])/(p[i]-s_dw[tot_dw-1])<=0)
  48. s_dw[tot_dw--]=point();
  49. s_dw[++tot_dw]=p[i];
  50. }
  51. while (tot_up>0) s_up[tot_up--]=point();
  52. D(i,n,1) {
  53. while (tot_up>=2&&(s_up[tot_up]-s_up[tot_up-1])/(p[i]-s_up[tot_up-1])<=0)
  54. s_up[tot_up--]=point();
  55. s_up[++tot_up]=p[i];
  56. }
  57. }
  58. #define x0 now.x
  59. #define y0 now.y
  60. #define A 0.00
  61. #define B 100.00
  62. int Check(point now) {
  63. if (y0==0)
  64. return (2*x0*s_dw[1].x>=x0*x0+y0*y0&&2*x0*s_dw[tot_dw].x>=x0*x0+y0*y0);
  65. point a(A,(x0*x0+y0*y0-2*x0*A)/(2*y0));
  66. point b(B,(x0*x0+y0*y0-2*x0*B)/(2*y0));
  67. if (y0>0) {
  68. int l=1,r=tot_dw;
  69. while (r-l>=3) {
  70. int _l=(l+l+r)/3;
  71. int _r=(l+r+r)/3;
  72. LD ql=(b-a)/(s_dw[_l]-a); if (ql<0) return 0;
  73. LD qr=(b-a)/(s_dw[_r]-a); if (qr<0) return 0;
  74. if (ql<qr) r=_r; else l=_l;
  75. }
  76. F(i,l,r) if ((b-a)/(s_dw[i]-a)<0) return 0;
  77. }
  78. else if (y0<0) {
  79. swap(a,b);
  80. int l=1,r=tot_up;
  81. while (r-l>=3) {
  82. int _l=(l+l+r)/3;
  83. int _r=(l+r+r)/3;
  84. LD ql=(b-a)/(s_up[_l]-a); if (ql<0) return 0;
  85. LD qr=(b-a)/(s_up[_r]-a); if (qr<0) return 0;
  86. if (ql<qr) r=_r; else l=_l;
  87. }
  88. F(i,l,r) if ((b-a)/(s_up[i]-a)<0) return 0;
  89. }
  90. return 1;
  91. }
  92. void Solve(int l,int r) {
  93. if (l==r) return;
  94. int mid=(l+r)>>1;
  95. if (l<=mid) Solve(l,mid);
  96. if (mid+1<=r) Solve(mid+1,r);
  97. while (n>0) p[n--]=point(); F(i,l,mid) if (op[i].kd==0) p[++n]=op[i].p; if (!n) return;
  98. Graham();
  99. F(i,mid+1,r) if (op[i].kd==1) {
  100. if (ans[i]) ans[i]=Check(op[i].p);
  101. cnt[i]++;
  102. }
  103. }
  104. int main(void) {
  105. #ifndef ONLINE_JUDGE
  106. freopen("sdchr.in","r",stdin);
  107. #endif
  108. m=rd();
  109. F(i,1,m) {
  110. int kd=rd(); LD x,y; scanf("%lf%lf",&x,&y);
  111. op[i]=OP(kd,point(x,y));
  112. }
  113. F(i,1,m) ans[i]=1;
  114. Solve(1,m);
  115. F(i,1,m) if (op[i].kd==1&&!cnt[i]) ans[i]=0;
  116. F(i,1,m) if (op[i].kd==1) if (ans[i]) printf("Yes\n"); else printf("No\n");
  117. return 0;
  118. }

【bzoj2300】【haoi2011】防线修建 离线处理+动态维护凸包

代码

  1. #include <bits/stdc++.h>
  2. #include <algorithm>
  3. using namespace std;
  4. #define F(i,a,b) for (int i=(a);i<=(b);i++)
  5. #define D(i,a,b) for (int i=(a);i>=(b);i--)
  6. #define fore(v,u) for (vector<int>::iterator v=g[u].begin();v!=g[u].end();v++)
  7. #define LL long long
  8. #define LD long double
  9. LL rd(void) {
  10. LL x=0,f=1; char c=getchar();
  11. for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;
  12. for (;isdigit(c);c=getchar()) x=x*10+c-'0';
  13. return x*f;
  14. }
  15. char rdc(void) {
  16. char c=getchar();
  17. while (!isalpha(c))
  18. c=getchar();
  19. return c;
  20. }
  21. struct point {
  22. double x,y;
  23. point(double _x=0,double _y=0):x(_x),y(_y){}
  24. friend point operator - (point a,point b) {
  25. return point(a.x-b.x,a.y-b.y);
  26. }
  27. friend int operator < (point a,point b) {
  28. if (a.x!=b.x) return a.x<b.x; else return a.y<b.y;
  29. }
  30. friend double operator / (point a,point b) {
  31. return a.x*b.y-a.y*b.x;
  32. }
  33. double norm(void) {
  34. return sqrt(x*x+y*y);
  35. }
  36. void Read(void) {
  37. x=rd(),y=rd();
  38. }
  39. };
  40. set<point> s;
  41. double sum;
  42. void Add(point x) {
  43. set<point>::iterator r=lower_bound(s.begin(),s.end(),x),l=r,t; l--;
  44. if ((x-*l)/(*r-*l)>0) return;
  45. sum-=(*r-*l).norm();
  46. while (1) {
  47. t=r; r++;
  48. if (r==s.end()) break;
  49. if ((*t-x)/(*r-x)<0) break;
  50. sum-=(*r-*t).norm();
  51. s.erase(t);
  52. }
  53. while (1) {
  54. if (l==s.begin()) break;
  55. t=l; l--;
  56. if ((x-*l)/(*t-*l)>0) break;
  57. sum-=(*t-*l).norm();
  58. s.erase(t);
  59. }
  60. s.insert(x);
  61. l=r=s.find(x);
  62. l--,r++;
  63. sum+=(*r-x).norm();
  64. sum+=(x-*l).norm();
  65. }
  66. #define M 262144
  67. int m; point p[M]; int v[M];
  68. int q,op[M][2]; double ans[M];
  69. int main(void) {
  70. #ifndef ONLINE_JUDGE
  71. freopen("sdchr.in","r",stdin);
  72. #endif
  73. int n=rd(),x=rd(),y=rd();
  74. s.insert(point(0,0));
  75. s.insert(point(n,0));
  76. s.insert(point(x,y));
  77. sum+=(point(0,0)-point(x,y)).norm();
  78. sum+=(point(x,y)-point(n,0)).norm();
  79. m=rd(); F(i,1,m) p[i].Read();
  80. q=rd();
  81. F(i,1,q) if (rd()==2) op[i][0]=2; else op[i][0]=1,v[op[i][1]=rd()]=1;
  82. F(i,1,m) if (!v[i]) Add(p[i]);
  83. D(i,q,1)
  84. if (op[i][0]==2) ans[i]=sum; else Add(p[op[i][1]]);
  85. F(i,1,q) if (op[i][0]==2) printf("%0.2lf\n",ans[i]);
  86. return 0;
  87. }

【bzoj1185】【hnoi2007】最小矩形覆盖 凸包+旋转卡壳

代码

  1. #include <cstdio>
  2. #include <cmath>
  3. #include <algorithm>
  4. using namespace std;
  5. #define F(i,a,b) for (int i=(a);i<=(b);i++)
  6. #define INF 1e30
  7. #define EPS 1e-8
  8. #define N 65536
  9. int n;
  10. struct point {
  11. double x,y;
  12. point(double _x=0,double _y=0) {
  13. x=_x,y=_y;
  14. }
  15. friend point operator + (point a,point b) {
  16. return point(a.x+b.x,a.y+b.y);
  17. }
  18. friend point operator - (point a,point b) {
  19. return point(a.x-b.x,a.y-b.y);
  20. }
  21. point operator * (double val) {
  22. return point(x*val,y*val);
  23. }
  24. void Read(void) {
  25. scanf("%lf%lf",&x,&y);
  26. }
  27. double norm(void) {
  28. return sqrt(pow(x,2)+pow(y,2));
  29. }
  30. }p[N],org;
  31. double dot(point a,point b) {
  32. return a.x*b.x+a.y*b.y;
  33. }
  34. double det(point a,point b) {
  35. return a.x*b.y-a.y*b.x;
  36. }
  37. int cmp(point a,point b) {
  38. return det(a-org,b-org)>0;
  39. }
  40. int tot;
  41. point s[N];
  42. double ans;
  43. point t[4];
  44. void Graham(void) {
  45. F(i,2,n) if (p[i].y<p[1].y||p[i].y==p[1].y&&p[i].x<p[1].x) swap(p[1],p[i]);
  46. org=p[1]; sort(p+2,p+n+1,cmp);
  47. F(i,1,n) {
  48. while (tot>=2&&det(s[tot]-s[tot-1],p[i]-s[tot-1])<=0)
  49. s[tot--]=point();
  50. s[++tot]=p[i];
  51. }
  52. s[0]=s[tot];
  53. }
  54. void Rot(void) {
  55. int l=0,r=0,p=0; ans=INF;
  56. F(i,1,tot-1) {
  57. if (det(s[1]-s[0],s[i]-s[0])>det(s[1]-s[0],s[p]-s[0])-EPS) p=i;
  58. if (dot(s[1]-s[0],s[i]-s[0])>dot(s[1]-s[0],s[r]-s[0])-EPS) r=i;
  59. if (dot(s[1]-s[0],s[i]-s[0])<dot(s[1]-s[0],s[l]-s[0])+EPS) l=i;
  60. }
  61. F(i,0,tot-1) {
  62. double D=(s[i+1]-s[i]).norm();
  63. while (det(s[i+1]-s[i],s[p+1]-s[i])>det(s[i+1]-s[i],s[p]-s[i])-EPS)
  64. p=(p+1)%tot;
  65. while (dot(s[i+1]-s[i],s[r+1]-s[i])>dot(s[i+1]-s[i],s[r]-s[i])-EPS)
  66. r=(r+1)%tot;
  67. while (dot(s[i+1]-s[i],s[l+1]-s[i])<dot(s[i+1]-s[i],s[l]-s[i])+EPS)
  68. l=(l+1)%tot;
  69. double L=dot(s[i+1]-s[i],s[l]-s[i])/D;
  70. double R=dot(s[i+1]-s[i],s[r]-s[i])/D;
  71. double H=det(s[i+1]-s[i],s[p]-s[i])/D; H=fabs(H);
  72. double tmp=(R-L)*H;
  73. if (tmp<ans) {
  74. ans=tmp;
  75. t[0]=s[i]+(s[i+1]-s[i])*(R/D);
  76. t[1]=t[0]+(s[r]-t[0])*(H/(t[0]-s[r]).norm());
  77. t[2]=t[1]-(t[0]-s[i])*((R-L)/(s[i]-t[0]).norm());
  78. t[3]=t[2]-(t[1]-t[0]);
  79. }
  80. }
  81. }
  82. int main(void) {
  83. #ifndef ONLINE_JUDGE
  84. freopen("a.in","r",stdin);
  85. #endif
  86. scanf("%d",&n); F(i,1,n) p[i].Read();
  87. Graham();
  88. Rot();
  89. printf("%0.5lf\n",ans);
  90. int x=0; F(i,1,3) if (t[i].y<t[x].y||t[i].y==t[x].y&&t[i].x<t[x].x) x=i;
  91. F(i,0,3) printf("%0.5lf %0.5lf\n",t[(i+x)%4].x,t[(i+x)%4].y);
  92. return 0;
  93. }

【zoj1081】Points Within - 判断一个点是否在多边形内

题意

给定一个任意的多边形,判断点在不在多边形内。

分析

过当前点做一条射线。
看经过的节点的情况。
为了特判经过端点的情况,把所有线段的值较大的端点当成空心的点。

代码

  1. #include <cstdio>
  2. #include <cctype>
  3. #include <algorithm>
  4. using namespace std;
  5. #define F(i,a,b) for (int i=(a);i<=(b);i++)
  6. #define INF 0x7fffffff
  7. int rd(void) {
  8. int x=0,f=1; char c=getchar();
  9. for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;
  10. for (;isdigit(c);c=getchar()) x=x*10+c-'0';
  11. return x*f;
  12. }
  13. #define N 128
  14. int n,m;
  15. struct point {
  16. double x,y;
  17. point(double _x=0,double _y=0) {
  18. x=_x,y=_y;
  19. }
  20. friend point operator - (point a,point b) {
  21. return point(a.x-b.x,a.y-b.y);
  22. }
  23. void Read(void) {
  24. scanf("%lf%lf",&x,&y);
  25. }
  26. }p[N];
  27. double det(point a,point b) {
  28. return a.x*b.y-a.y*b.x;
  29. }
  30. int Online(point a,point b,point x) {
  31. if (det(x-a,b-a)!=0) return 0;
  32. double minx=min(a.x,b.x),maxx=max(a.x,b.x);
  33. double miny=min(a.y,b.y),maxy=max(a.y,b.y);
  34. return minx<=x.x&&x.x<=maxx&&miny<=x.y&&x.y<=maxy;
  35. }
  36. int PNPoly(point x) {
  37. int c=0;
  38. F(i,0,n-1)
  39. if (Online(p[i],p[i+1],x))
  40. return 1;
  41. F(i,0,n-1) {
  42. double k=det(p[i+1]-p[i],x-p[i]);
  43. if (k>0&&p[i].y<=x.y&&x.y<p[i+1].y) c++;
  44. if (k<0&&p[i+1].y<=x.y&&x.y<p[i].y) c--;
  45. }
  46. return c!=0;
  47. }
  48. int main(void) {
  49. #ifndef ONLINE_JUDGE
  50. freopen("a.in","r",stdin);
  51. #endif
  52. F(c,1,INF) {
  53. n=rd(); if (!n) break; m=rd();
  54. F(i,1,n) p[i].Read(); p[0]=p[n];
  55. if (n>=2) {
  56. double t=det(p[2]-p[1],p[1]-p[0]);
  57. if (t>0) F(i,0,n>>1) swap(p[i],p[n-i]);
  58. }
  59. if (c!=1) printf("\n");
  60. printf("Problem %d:\n",c);
  61. F(i,1,m) {
  62. point x; x.Read();
  63. if (PNPoly(x)) printf("Within\n"); else printf("Outside\n");
  64. }
  65. }
  66. return 0;
  67. }

【hdu2108】Shape of HDU - 判定是不是凸包

题意

如标题所示

分析

使用判断。
记得判断第一个点与最后一个点的连边也要满足是凸的。

在直观理解叉积上,需要注意两点。
一个是平移的观点。
另一个是>0在下面,<0在上面,=0共线。

如果凸包可能是顺时针的,可能是逆时针的。
需要这样进行调整:

  1. double t=det(p[2]-p[1],p[1]-p[0]);
  2. if (t>0) F(i,0,n>>1) swap(p[i],p[n-i]);

代码

  1. #include <cstdio>
  2. #include <cctype>
  3. #include <algorithm>
  4. using namespace std;
  5. #define F(i,a,b) for (int i=(a);i<=(b);i++)
  6. int rd(void) {
  7. int x=0,f=1; char c=getchar();
  8. for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;
  9. for (;isdigit(c);c=getchar()) x=x*10+c-'0';
  10. return x*f;
  11. }
  12. #define N 128
  13. int n;
  14. struct point {
  15. double x,y;
  16. point(double _x=0,double _y=0) {
  17. x=_x,y=_y;
  18. }
  19. friend point operator - (point a,point b) {
  20. return point(a.x-b.x,a.y-b.y);
  21. }
  22. void Read(void) {
  23. x=rd(),y=rd();
  24. }
  25. }p[N];
  26. double det(point a,point b) {
  27. return a.x*b.y-a.y*b.x;
  28. }
  29. int is_convex(point *p,int n) {
  30. F(i,2,n) {
  31. double t=det(p[i]-p[i-1],p[i-1]-p[i-2]);
  32. if (t>0) return 0;
  33. }
  34. return 1;
  35. }
  36. int main(void) {
  37. #ifndef ONLINE_JUDGE
  38. freopen("a.in","r",stdin);
  39. #endif
  40. while (1) {
  41. n=rd();
  42. if (!n) break;
  43. if (n<=2) {
  44. printf("concave\n");
  45. continue;
  46. }
  47. F(i,1,n) p[i].Read(); p[0]=p[n];
  48. /*
  49. double t=det(p[2]-p[1],p[1]-p[0]);
  50. if (t>0) F(i,0,n>>1) swap(p[i],p[n-i]);
  51. */
  52. if (is_convex(p,n)) printf("convex\n"); else printf("concave\n");
  53. }
  54. return 0;
  55. }

【bzoj1069】【scoi2007】最大土地面积 凸包+旋转卡壳

题意

      在某块平面土地上有个点,你可以选择其中的任意四个点,将这片土地围起来,当然,你希望这四个点围成的多边形面积最大。

分析

      首先,我们选择的四个点一定是多边形的顶点。所以我们先用Graham算法求出凸包。注意求凸包的正确姿势。det(a,b)<0,直接说明a在b的上面,类似的,有det(a,b)=0和det(a,b)>0。

      然后,考虑怎么求最大的面积。我们可以考虑枚举一条对角线,暴力算左边和右边的最优情况。时间复杂度为,但是会TLE。

      考虑根据凸包的性质进行优化。我们枚举对角线上的一个点,按照极角序枚举另一个点,那么最大的面积的点必然在单调的移动。所以优化到了。这貌似叫旋转卡壳?

      关于实现上,多边形的面积考虑使用叉积来求。

代码

  1. #include <cstdio>
  2. #include <cmath>
  3. #include <algorithm>
  4. using namespace std;
  5. #define F(i,a,b) for (int i=(a);i<=(b);i++)
  6. #define MIN -1e30
  7. #define N 2048
  8. int n;
  9. struct point {
  10. double x,y;
  11. point(double _x=0,double _y=0) {
  12. x=_x,y=_y;
  13. }
  14. friend point operator - (point a,point b) {
  15. return point(a.x-b.x,a.y-b.y);
  16. }
  17. void Read(void) {
  18. scanf("%lf%lf",&x,&y);
  19. }
  20. }p[N],org;
  21. double det(point a,point b) {
  22. return a.x*b.y-a.y*b.x;
  23. }
  24. int cmp(point a,point b) {
  25. return det(a-org,b-org)<0;
  26. }
  27. double sqr(point a,point b,point c) {
  28. return fabs(det(b-a,c-a))/2;
  29. }
  30. point s[N]; int tot;
  31. void Graham(void) {
  32. int k=1; F(i,2,n) if (p[i].y<p[k].y||p[i].y==p[k].y&&p[i].x<p[k].x) k=i;
  33. swap(p[1],p[k]); org=p[1];
  34. sort(p+2,p+n+1,cmp);
  35. s[++tot]=p[1],s[++tot]=p[2];
  36. F(i,3,n) {
  37. while (tot>=2&&det(s[tot]-s[tot-1],p[i]-s[tot-1])>=0)
  38. s[tot--]=point();
  39. s[++tot]=p[i];
  40. }
  41. }
  42. double RC(void) {
  43. double ans=MIN;
  44. F(x,1,tot) {
  45. int a=x%tot+1;
  46. int b=(x+2)%tot+1;
  47. F(y,x+2,tot) {
  48. while (a%tot+1!=y&&sqr(s[x],s[y],s[a])<sqr(s[x],s[y],s[a%tot+1]))
  49. a=a%tot+1;
  50. while (b%tot+1!=x&&sqr(s[x],s[y],s[b])<sqr(s[x],s[y],s[b%tot+1]))
  51. b=b%tot+1;
  52. ans=max(ans,sqr(s[x],s[y],s[a])+sqr(s[x],s[y],s[b]));
  53. }
  54. }
  55. return ans;
  56. }
  57. int main(void) {
  58. #ifndef ONLINE_JUDGE
  59. freopen("a.in","r",stdin);
  60. #endif
  61. scanf("%d",&n); F(i,1,n) p[i].Read();
  62. Graham();
  63. double ans=RC();
  64. printf("%.3lf\n",ans);
  65. return 0;
  66. }

【bzoj3203】【sdoi2013】保护出题人 凸包+三分

分析

PoPoQQQ题解 之 传送门

关键掌握一下三分的写法。

  1. double Query(point o) {
  2. int l=1,r=tot;
  3. while (r-l>=3) {
  4. int l_mid=(l+l+r)/3,r_mid=(l+r+r)/3;
  5. double _l=slope(s[l_mid],o);
  6. double _r=slope(s[r_mid],o);
  7. if (_l>_r)
  8. r=r_mid;
  9. else l=l_mid;
  10. }
  11. double res=0;
  12. F(i,l,r)
  13. res=max(res,slope(s[i],o));
  14. return res;
  15. }

大范围三分,小范围枚举,这样肯定是没有问题的。

代码

  1. #include <cstdio>
  2. #include <cctype>
  3. #include <algorithm>
  4. using namespace std;
  5. #define F(i,a,b) for (int i=(a);i<=(b);i++)
  6. #define LL long long
  7. #define INF 1e30
  8. LL rd(void) {
  9. LL x=0,f=1; char c=getchar();
  10. for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;
  11. for (;isdigit(c);c=getchar()) x=x*10+c-'0';
  12. return x*f;
  13. }
  14. #define N 131072
  15. int n; LL d;
  16. LL a[N],x[N];
  17. int tot;
  18. struct point {
  19. double x,y;
  20. point(double _x=0,double _y=0) {
  21. x=_x,y=_y;
  22. }
  23. friend point operator - (point a,point b) {
  24. return point(a.x-b.x,a.y-b.y);
  25. }
  26. friend double operator ^ (point a,point b) {
  27. return a.x*b.y-a.y*b.x;
  28. }
  29. }s[N];
  30. void Add(point a) {
  31. while (tot>=2)
  32. if (((s[tot]-s[tot-1])^(a-s[tot-1]))<=0)
  33. s[tot--]=point();
  34. else break;
  35. s[++tot]=a;
  36. }
  37. double slope(point a,point b) {
  38. return (a.y-b.y)/(a.x-b.x);
  39. }
  40. double Query(point o) {
  41. int l=1,r=tot;
  42. while (r-l>=3) {
  43. int l_mid=(l+l+r)/3,r_mid=(l+r+r)/3;
  44. double _l=slope(s[l_mid],o);
  45. double _r=slope(s[r_mid],o);
  46. if (_l>_r)
  47. r=r_mid;
  48. else l=l_mid;
  49. }
  50. double res=0;
  51. F(i,l,r)
  52. res=max(res,slope(s[i],o));
  53. return res;
  54. }
  55. int main(void) {
  56. #ifndef ONLINE_JUDGE
  57. freopen("a.in","r",stdin);
  58. #endif
  59. n=rd(),d=rd();
  60. F(i,1,n) a[i]=rd(),x[i]=rd();
  61. F(i,1,n) a[i]+=a[i-1];
  62. double sum=0;
  63. F(i,1,n) {
  64. Add(point(i*d,a[i-1]));
  65. double t=Query(point(i*d+x[i],a[i]));
  66. sum+=t;
  67. }
  68. printf("%.0lf\n",sum);
  69. return 0;
  70. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注