P2611 [ZJOI2012]小蓝的好友

题目描述

终于到达了这次选拔赛的最后一题,想必你已经厌倦了小蓝和小白的故事,为了回馈各位比赛选手,此题的主角是贯穿这次比赛的关键人物——小蓝的好友。

在帮小蓝确定了旅游路线后,小蓝的好友也不会浪费这个难得的暑假。与小蓝不同,小蓝的好友并不想将时间花在旅游上,而是盯上了最近发行的即时战略游戏——SangoCraft。但在前往通关之路的道路上,一个小游戏挡住了小蓝的好友的步伐。

“国家的战争其本质是抢夺资源的战争”是整款游戏的核心理念,这个小游戏也不例外。简单来说,用户需要在给定的长方形土地上选出一块子矩形,而系统随机生成了N个资源点,位于用户所选的长方形土地上的资源点越多,给予用户的奖励也越多。悲剧的是,小蓝的好友虽然拥有着极其优秀的能力,但同时也有着极差的RP,小蓝的好友所选的区域总是没有一个资源点。

终于有一天,小蓝的好友决定投诉这款游戏的制造厂商,为了搜集证据,小蓝的好友想算出至少包含一个资源点的区域的数量。作为小蓝的好友,这自然是你分内之事。

输入输出格式

输入格式:

每个输入文件中仅包含一个测试数据。

第一行包含由两个空格隔开的正整数\(R\),\(C\),\(N\),表示游戏在一块\([1,R] \times [1,C]\)的地图上生成了\(N\)个资源点。

接下来有\(N\)行,每行包含两个整数 \(x,y\),表示这个资源点的坐标

\((1 \le x \le r,1 \le y \le C)\)

输出格式:

输出文件应仅包含一个整数,表示至少包含一个资源点的区域的数量。

具体的说,设\(N\)个资源点的坐标为\((i=1..n)\),你需要计算有多少个四元组\((L_B,D_B,R_B,U_B)\)满足\(1<=L_B<=R_B<=R,1<=D_B<=U_B<=C\),且存在一个\(i\)使得 \(L_B<=x_i<=R_B,D_B<=y_i<=U_B\)均成立。

说明

对于\(20\%\)的数据,\(N<=50\)。

对于\(40\%\)的数据,\(N<=2000\)。

对于\(100\%\)的数据,\(R,C<=40000,N<=100000\),资源点的位置两两不同,且位置为随机生成。


我们首先弄清楚我们咋统计的

先把矩形蓝白出来

然后我们对矩形固定一个下边界,设为\(down\)

然后我们枚举所取矩形的左边界与右边界

如何不重不漏的把所有可行上边界统计呢?

比方说,黑线是矩形下边界,左右边界现在是任意枚举的,那么红色箭头范围内就是上边界可取的集合了

我们发现,上边界的最下取值点与最低的那个点相连

那么我们可以枚举每个左右边界,然后找到最低的那个点,我们就得到了一个优秀的\(O(N^4)\)的解法辣

注:这里把矩形规模称作\(N\),把点的个数称作\(K\)

取最低点的优化很容易搞成\(O(N^3)\)的,然而这样布星。


我们像CDQ分治那样进行统计

具体的,对每一个固定的下边界,每一列都有唯一确定的最低的点

我们以第\(x\)列的\(x\)为二叉排序树的关键字,以那个最低的点的行数\(y\)为大根堆的关键字,建立一颗\(treap\)

在统计每一个固定的下边界时,每个点的贡献都是 (左儿子大小+1)\(\times\) (右儿子大小+1) \(\times\) 堆的关键字

表示,左边区间可取集合,右边区间可取集合和上边界可取集合

当然堆值可能会变,我们需要在改变的时候进行调整

这时候一个很显然的\(O(N^2)\)做法就有了

我们改完一行去遍历整棵树就可以了。

至于修改的复杂度,因为数据随机,可以看做是\(O(KlogN)\)的

如果我们对每个点维护它及它儿子的贡献,每次改的时候就只需要查询根节点就行辣

复杂度:\(O(KlogN)\)(数据随机)


Code:

  1. #include <cstdio>
  2. #include <algorithm>
  3. #define ls ch[now][0]
  4. #define rs ch[now][1]
  5. #define fa par[now]
  6. #define ll long long
  7. const int N=1e5+10;
  8. const int M=4e4+10;
  9. int n,m,k;
  10. std::pair <int,int > dx[N];
  11. ll sum[M],dat[M],siz[M],ans;int ch[M][2],par[M],root;
  12. int build(int l,int r)
  13. {
  14. if(l>r) return 0;
  15. if(l==r) {siz[l]=1;return l;}
  16. int now=l+r>>1;
  17. ls=build(l,now-1);
  18. if(ls) par[ls]=now;
  19. rs=build(now+1,r);
  20. if(rs) par[rs]=now;
  21. siz[now]=siz[ls]+siz[rs]+1;
  22. return now;
  23. }
  24. void updata(int now)
  25. {
  26. sum[now]=dat[now]*(siz[ls]+1ll)*(siz[rs]+1ll)+sum[ls]+sum[rs];
  27. siz[now]=siz[ls]+siz[rs]+1;
  28. }
  29. int identity(int now){return ch[fa][1]==now;}
  30. void connect(int f,int now,int typ){fa=f;ch[f][typ]=now;}
  31. void Rotate(int now)
  32. {
  33. int p=fa,typ=identity(now);
  34. if(p==root) root=now;
  35. connect(p,ch[now][typ^1],typ);
  36. connect(par[p],now,identity(p));
  37. connect(now,p,typ^1);
  38. updata(p),updata(now);
  39. }
  40. int main()
  41. {
  42. scanf("%d%d%d",&n,&m,&k);
  43. root=build(1,m);
  44. for(int i=1;i<=k;i++)
  45. scanf("%d%d",&dx[i].first,&dx[i].second);
  46. std::sort(dx+1,dx+1+k);
  47. int las=1;dat[0]=n+1;
  48. for(int i=1;i<=k;i++)
  49. {
  50. while(las!=dx[i].first)
  51. ans+=sum[root],++las;
  52. int now=dx[i].second;
  53. dat[now]=dx[i].first;
  54. while(dat[fa]<dat[now])
  55. Rotate(now);
  56. while(now) updata(now),now=fa;
  57. }
  58. while(las<=n)
  59. ans+=sum[root],++las;
  60. printf("%lld\n",ans);
  61. return 0;
  62. }

2018.8.26

洛谷 P2611 [ZJOI2012]小蓝的好友 解题报告的更多相关文章

  1. 洛谷 P2323 [HNOI2006]公路修建问题 解题报告

    P2323 [HNOI2006]公路修建问题 题目描述 输入输出格式 输入格式: 在实际评测时,将只会有m-1行公路 输出格式: 思路: 二分答案 然后把每条能加的大边都加上,然后加小边 但在洛谷的题 ...

  2. 洛谷 P1852 [国家集训队]跳跳棋 解题报告

    P1852 [国家集训队]跳跳棋 题目描述 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子. 我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在\(a\),\(b\), ...

  3. 洛谷 P3299 [SDOI2013]保护出题人 解题报告

    P3299 [SDOI2013]保护出题人 题目描述 出题人铭铭认为给SDOI2012出题太可怕了,因为总要被骂,于是他又给SDOI2013出题了. 参加SDOI2012的小朋友们释放出大量的僵尸,企 ...

  4. 洛谷 P2059 [JLOI2013]卡牌游戏 解题报告

    P2059 [JLOI2013]卡牌游戏 题意 有\(n\)个人玩约瑟夫游戏,有\(m\)张卡,每张卡上有一个正整数,每次庄家有放回的抽一张卡,干掉从庄家起顺时针的第\(k\)个人(计算庄家),干掉的 ...

  5. 洛谷 P2463 [SDOI2008]Sandy的卡片 解题报告

    P2463 [SDOI2008]Sandy的卡片 题意 给\(n(\le 1000)\)串,定义两个串相等为"长度相同,且一个串每个数加某个数与另一个串完全相同",求所有串的最长公 ...

  6. 洛谷 P2774 方格取数问题 解题报告

    P2774 方格取数问题 题目背景 none! 题目描述 在一个有 \(m*n\) 个方格的棋盘中,每个方格中有一个正整数.现要从方格中取数,使任意 2 个数所在方格没有公共边,且取出的数的总和最大. ...

  7. 洛谷 画栅栏Painting the Fence 解题报告

    P2205 画栅栏Painting the Fence 题目描述 \(Farmer\) \(John\) 想出了一个给牛棚旁的长围墙涂色的好方法.(为了简单起见,我们把围墙看做一维的数轴,每一个单位长 ...

  8. 洛谷 P2764 最小路径覆盖问题 解题报告

    P2764 最小路径覆盖问题 问题描述: 给定有向图\(G=(V,E)\).设\(P\) 是\(G\) 的一个简单路(顶点不相交)的集合.如果\(V\) 中每个顶点恰好在\(P\) 的一条路上,则称\ ...

  9. 洛谷 P2057 [SHOI2007]善意的投票 解题报告

    P2057 [SHOI2007]善意的投票 题目描述 幼儿园里有n个小朋友打算通过投票来决定睡不睡午觉.对他们来说,这个问题并不是很重要,于是他们决定发扬谦让精神.虽然每个人都有自己的主见,但是为了照 ...

随机推荐

  1. 百度app红包? 百度全家桶?果断卸载

    听说今年的春晚红包与百度合作.这不 刚又下载了一个百度app,之前下载过,太卡了,用户体验极.本身对百度也没啥好感,再加上这周看了:百度已死的文章,搜索全百家号.具体啥情况,你们百度搜一搜吧

  2. php开发aes加密总结

    <?php class Aes { /** * aes 加密 解密类库 * @by singwa * Class Aes *说明:本类只适用于加密字符串 * */ private $key = ...

  3. Java基础——继承和多态

    面向对象的编程允许从已经存在的类中定义新的类,这称为继承. 面向过程的范式重点在于方法的设计,而面向对象的范式将数据和方法结合在对象中.面向对象范式的软件设计着重于对象以及对象上的操作.面向对象的方法 ...

  4. plsql 连接数据库无法解析指定的连接标识符

    之前用plsql连接的时候一直出问题,报无法解析指定的连接标识符,但是我加上ip地址就可以连接上. 我百度了很久,有说如下图选择oracle home的,有说清空admin目录下的所有文件, 但是都不 ...

  5. Leecode刷题之旅-C语言/python-111二叉树的最小深度

    /* * @lc app=leetcode.cn id=111 lang=c * * [111] 二叉树的最小深度 * * https://leetcode-cn.com/problems/minim ...

  6. centos 7 关闭IPtables

    systemctl status iptables.service systemctl stopiptables.service

  7. shell重温---基础篇(参数传递&echo命令)

    经过前两天的学习,关于shell的基础算是知道的一般般啦,最起码不算是小白了(纯属意淫).今天就来点干货哈.   首先是运行shell脚本时的参数传递.脚本内获取参数的格式为$n.n代表了一个数字,例 ...

  8. MySQL分区的限制(最多有多少个分区)

    MySQL分区的限制 •   只能对数据表的整型列进行分区,或者数据列可以通过分区函数转化成整型列 •   最大分区数目不能超过1024 •   如果含有唯一索引或者主键,则分区列必须包含在所有的唯一 ...

  9. Borland和Micorsoft的对话(转载自月光软件网)

      Borland与Microsoft关于Delphi的对话 Bear 1.Delphi较贵  一套Delphi的价格大约相当于两套Visual Studio  ------------------- ...

  10. MySQL数据库性能优化专题

    摘录: 书:<MySQL性能调优与架构设计> 一个系列: (按顺序排一下) MySQL 数据库性能优化之缓存参数优化 http://isky000.com/database/mysql-p ...