Problem

loj3085 bzoj不放题面差评

题意概要:给出两条竖直直线,再给出 \(n\) 架飞机的初始航线:一条接通这两条直线的线段,保证航线交点不在两条直线上。现要求安排所有飞机在航线相交处做特技:

  • 擦身而过:两架飞机按原方向线路继续前进,一次得分 \(b\)
  • 对向交换:两架飞机交换线路继续前进,一次得分 \(a\)

另外,给定 \(k\) 个边界与坐标轴成 \(45°\)角 的正方形,若一次特技被至少一个正方形囊括,则总得分加 \(c\)

现要求决策每次相遇做的特技,求最大/最小收益

同时要求决策方案中所有飞机 在两条竖直直线处 按纵坐标的排序 相同

\(n, Q\leq 10^5\)

交点个数 \(\leq 5\times 10^5\)

这题意概要好像和原题面差不多了qwq

Solution

\(\mathrm{GXOI/GZOI2019}\) 的题好毒瘤啊,两道联赛、两道原题、一道麻将题……完全不想打,就这题还有点意思……还偏偏要整个二合一……

交点个数 \(\leq 5\times 10^5\),应该是暗示要暴力求出来:交点一定是右部直线排序的逆序对(左部已经有序),用个 \(set\) 暴力扫就是 \(O(n\log n)\)。就得到了所有交点

\(c\) 的贡献很明显是单独求的,将坐标系旋转 \(45°\) 后就可以扫描线了。所以其实难度在于如何求 \(a,b\) 的贡献

设交点总数为 \(t\),其中有 \(x\) 个点交换航线,\(t-x\) 个点不交换。这部分贡献是 \(ax+b(t-x)=(a-b)x+bt\),所以总得分的最大最小值一定是 \(x\) 取最值时取得,即只需要求最少/多有多少个点交换航线

首先因为要求飞机在起终点的顺序不变,而交换航线不会改变顺序,所有点都交换航线肯定是可行的,即 \(x_{\max}=t\)

再考虑最小值。假如所有点都不换航线(\(x = 0\)),在大部分情况下都不合法,考虑使用最少的交换航线使得最终状态与初始状态一致:可以发现,若按照原航线行进时,飞机状态的变化产生了 \(s_1\rightarrow s_2\rightarrow ...\rightarrow s_m\rightarrow s_1\) 的循环,则可以使用 \(m-1\) 次交换使得方案合法(一次交换可以使得一架且最多一架飞机到达指定位置,使 \(m-1\) 架飞机合法后剩下的那一架飞机也即合法)

那么需要交换的次数为 "\(n-\)循环的个数"

复杂度为 \(O(n\log n+k\log k)\),瓶颈在暴力找交点和扫描线

Code

代码中 get_cross 为暴力找交点,Circle 为找循环,Extra 为扫描线

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. inline void read(int&x){
  4. char c11=getchar();x=0;while(!isdigit(c11))c11=getchar();
  5. while(isdigit(c11))x=x*10+c11-'0',c11=getchar();
  6. }
  7. const double eps = 1e-6;
  8. const int N = 101000, M = 501000;
  9. int l0[N], r0[N];
  10. int n,L,R;
  11. struct pnt {
  12. double x, y;
  13. friend inline bool operator < (const pnt&A,const pnt&B) {return A.x < B.x;}
  14. }p[M];
  15. int p0;
  16. pnt crs(int i,int j) {
  17. double th = (double)abs(l0[i] - l0[j]) / (abs(l0[i] - l0[j]) + abs(r0[i] - r0[j]));
  18. return (pnt) {L + (R-L) * th, l0[i] + (r0[i] - l0[i]) * th};
  19. }
  20. set <int> c;
  21. set <int> :: iterator itr;
  22. map <int,int> mp;
  23. int get_cross() {
  24. for(int i=1;i<=n;++i) {
  25. c.insert(r0[i]);
  26. mp[r0[i]] = i;
  27. itr = c.find(r0[i]);
  28. for(++itr; itr != c.end(); ++itr) {
  29. int j = mp[*itr];
  30. p[++p0] = crs(i, j);
  31. }
  32. }
  33. return p0;
  34. }
  35. namespace Circle {
  36. int b[N], dad[N];
  37. int find(int x) {return dad[x] ? dad[x] = find(dad[x]) : x;}
  38. int main() {
  39. for(int i=1;i<=n;++i) b[i] = r0[i];
  40. sort(b+1,b+n+1);
  41. int res = 0;
  42. for(int i=1,j,p1,p2;i<=n;++i) {
  43. j = lower_bound(b+1,b+n+1,r0[i])-b;
  44. if((p1 = find(i)) == (p2 = find(j))) ++res;
  45. else dad[p1] = p2;
  46. }
  47. return p0 - (n - res);
  48. }
  49. }
  50. namespace Extra {
  51. double b[M+N+N];
  52. int Q, tot;
  53. struct LNE {
  54. double x, y1, y2; int w;
  55. friend inline bool operator < (const LNE&A,const LNE&B) {return A.x < B.x;}
  56. }l[N+N];
  57. namespace BIT {
  58. #define lb(x) (x&(-x))
  59. int d[M+N+N];
  60. inline int qry(int x) {
  61. int res = 0;
  62. for(int i=x;i;i-=lb(i)) res += d[i];
  63. return res;
  64. }
  65. inline void upd(int l, int r, int w) {
  66. for(;l<=tot;l+=lb(l)) d[l] += w;
  67. for(++r;r<=tot;r+=lb(r)) d[r] -= w;
  68. }
  69. #undef lb
  70. }
  71. void input() {
  72. double x, y;
  73. for(int i=1;i<=p0;++i) {
  74. x = p[i].x, y = p[i].y;
  75. p[i].x = x + y, p[i].y = x - y;
  76. b[++tot] = p[i].y;
  77. }
  78. sort(p+1,p+p0+1);
  79. int r; read(Q);
  80. for(int i=1;i<=Q;++i) {
  81. scanf("%lf%lf",&x,&y), read(r);
  82. l[i+i-1].x = x + y - r - eps;
  83. l[i+i-1].y1 = x - r - y - eps;
  84. l[i+i-1].y2 = x - y + r + eps;
  85. l[i+i-1].w = 1;
  86. l[i+i].x = x + y + r + eps;
  87. l[i+i].y1 = x - y - r - eps;
  88. l[i+i].y2 = x + r - y + eps;
  89. l[i+i].w = -1;
  90. b[++tot] = x - y + r + eps;
  91. b[++tot] = x - y - r - eps;
  92. }
  93. Q <<= 1;
  94. sort(l+1,l+Q+1);
  95. sort(b+1,b+tot+1);
  96. int tt0 = 0; b[0] = -1e10;
  97. for(int i=1;i<=tot;++i)
  98. if(fabs(b[i] - b[i-1]) > eps)
  99. b[++tt0] = b[i];
  100. tot = tt0;
  101. for(int i=1;i<=p0;++i) p[i].y = lower_bound(b+1,b+tot+1,p[i].y) - b;
  102. for(int i=1;i<=Q;++i) {
  103. l[i].y1 = lower_bound(b+1,b+tot+1,l[i].y1) - b;
  104. l[i].y2 = lower_bound(b+1,b+tot+1,l[i].y2) - b;
  105. }
  106. }
  107. int main() {
  108. input();
  109. int res = 0;
  110. for(int i=1,j=1;i<=p0;++i) {
  111. while(j <= Q and l[j].x <= p[i].x)
  112. BIT::upd(l[j].y1, l[j].y2, l[j].w), ++j;
  113. if(BIT::qry(p[i].y)) ++res;
  114. }
  115. return res;
  116. }
  117. }
  118. int main() {
  119. int A, B, C;
  120. read(n), read(A), read(B), read(C);
  121. read(L), read(R);
  122. for(int i=1;i<=n;++i) read(l0[i]);
  123. for(int i=1;i<=n;++i) read(r0[i]);
  124. int ans1 = A * get_cross(), ans2 = ans1, exa;
  125. ans2 += (B - A) * Circle::main();
  126. exa = C * Extra::main();
  127. if(ans1 > ans2) swap(ans1, ans2);
  128. printf("%d %d\n",ans1 + exa, ans2 + exa);
  129. return 0;
  130. }

题解-GXOI/GZOI2019 特技飞行的更多相关文章

  1. P5302 [GXOI/GZOI2019]特技飞行

    题目地址:P5302 [GXOI/GZOI2019]特技飞行 这里是官方题解(by lydrainbowcat) 题意 给 \(10^5\) 条直线,给 \(x = st\) 和 \(x = ed\) ...

  2. luogu P5302 [GXOI/GZOI2019]特技飞行

    传送门 强行二合一可还行 首先\(c\)的贡献是不会变的,先考虑求出多少交点被矩形覆盖,交点的话可以按左端点纵坐标从下到上顺序枚举一条线段,然后维护右端点纵坐标的set,把之前处理过线段的右端点放进s ...

  3. [GXOI/GZOI2019]特技飞行

    题目链接 [https://www.luogu.org/problem/P5302] 思路:这道题可以说是两道题的合并.注意到\(c\)的分数与 \(a\)和\(b\)的分数 无关,也就是说可以分成两 ...

  4. 题解:[GXOI/GZOI2019]与或和

    开始完全没思路 在洛谷看到样例一,突发奇想,决定先做一下元素只有0/1的情况 发现子任务1是全1子矩阵 子任务2是总子矩阵个数减去全0子矩阵 发现全0/1矩阵可以构造单调栈解决.具体做法:前缀和求出每 ...

  5. [GX/GZOI2019]特技飞行(扫描线+置换)

    感觉是6题中最难的一题,其实这题是一个二合一: 第一问:给定平面上若干点和k个关键点,关键点覆盖一个45°倾斜的正方形范围r,求有多少点被至少一个关键点覆盖.这个可以曼哈顿转切比雪夫距离,然后再扫描线 ...

  6. GXOI/GZOI2019题解

    GXOI/GZOI2019题解 P5300 [GXOI/GZOI2019]与或和 一眼题.. 显然枚举每个二进制位,答案就变成了全1子矩阵数量. 这个xjb推推,单调栈一下就行了. #include& ...

  7. Loj #3085. 「GXOI / GZOI2019」特技飞行

    Loj #3085. 「GXOI / GZOI2019」特技飞行 题目描述 公元 \(9012\) 年,Z 市的航空基地计划举行一场特技飞行表演.表演的场地可以看作一个二维平面直角坐标系,其中横坐标代 ...

  8. 【LOJ】#3085. 「GXOI / GZOI2019」特技飞行

    LOJ#3085. 「GXOI / GZOI2019」特技飞行 这显然是两道题,求\(C\)是一个曼哈顿转切比雪夫后的线段树扫描线 求\(AB\),对向交换最大化和擦身而过最大化一定分别为最大值和最小 ...

  9. 「GXOI / GZOI2019」简要题解

    「GXOI / GZOI2019」简要题解 LOJ#3083. 「GXOI / GZOI2019」与或和 https://loj.ac/problem/3083 题意:求一个矩阵的所有子矩阵的与和 和 ...

随机推荐

  1. Google Chrome即将开始警告—停止支持Flash Player

    Adobe 计划在 2020 年让 Flash Player 彻底退休,整个科技行业都在为这个关键时刻做准备,包括浏览器开发机构,Google 作为最主要的一员,试图尽可能顺利地完成 Flash Pl ...

  2. 关于win7+VS2017环境下的opencv-contirb配置的一个坑

    问题出现背景: 由于课题需要用到SURF detector, 我依照网上的一下教程,把opencv-contrib的配置了一遍.但是,当我写了一个小demo来测试模块是否能正常使用的时候,程序能正常编 ...

  3. Smart Indenter for VBE(64bits smart indent addin for VBA Editor),VBA开发必备的智能排版工具。

    原始出处:www.cnblogs.com/Charltsing/p/SmartIndenter64.html 作者QQ: 564955427 最近更换电脑,改用64位office做开发.VBA代码美化 ...

  4. 4月23日 MySQL学习-DDL

    今日学习的是DDL的操作(数据定义语言) create table teachers (id int,name varchar(50));//创建一个表 给了两个类型alter table stude ...

  5. Glide和Picasso的区别

    首先简单的介绍下两个库的出身: Picasso是Square公司出品的一款非常优秀的开源图片加载库Glide是由Google开发,基于 Picasso,依然有保存了Picasso的简洁风格,但是在此做 ...

  6. OpenStack 命令行速查表

    OpenStack 命令行速查表   updated: 2017-07-18 08:53 Contents 认证 (keystone) 镜像(glance) 计算 (nova) 实例的暂停.挂起.停止 ...

  7. bzoj 5301: [Cqoi2018]异或序列 (莫队算法)

    链接:https://www.lydsy.com/JudgeOnline/problem.php?id=5301 题面; 5301: [Cqoi2018]异或序列 Time Limit: 10 Sec ...

  8. 简单 php 代码跟踪调试实现

    简单 php 代码跟踪调试实现 debug_backtrace:生成回溯 debug_print_backtrace:打印回溯 1. debug_backtrace ($options = DEBUG ...

  9. magento-2.2.6-1VM环境镜像-沙箱 - - 完全隔离的环境

    打包处理下载地址: 链接:https://pan.baidu.com/s/1HX0WjWEN8Wc-4TDvgEWMog 提取码:s2ls 官方下载 文档 BITNAMI MAGENTO堆栈虚拟机 B ...

  10. js中字符串可以调用的方法

    var s = "hello,world"   //定义一个字符串 s.length()                   // => 11 s.charAt(0)     ...