分治(完美子图)
时间:2020-07-11
本文章向大家介绍分治(完美子图),主要包括分治(完美子图)使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
- 完美子图
-
题目描述
- 小Q和小P 都非常喜欢做一些有趣的题目,他们经常互相出一些题目来考对方。
- 一天,小Q给小P出了这样一道题目:给出一个n*n 的网格图,在网格中放置n个点,(不会有两个点放置在同一个网格中)。如果一个m*m(1<=m<=n)的子网格图恰好包含m个点,则称这样的子网格图为完美子网格图。
- 现在小Q问小 P,对于给定的网格图存在多少个完美子网格图。小P这回被难住了,他请你来帮忙,你能帮他解决这个问题吗?
输入格式
- 第一行,一个正整数n,表示网格图的大小以及点的数量。
- 接下来n行,每行两个整数xi,yi,表示第i个点的坐标。
输出格式
样例
数据范围与提示
- 显然,分别以(2,2),(4,4)为左上,右下顶点的一个子网格图中有 个点,我们找到了一个完美子网格图,类似的完美子网格图在原图中能找出10个。
- n<=50000
- 思路:二维难以处理将其压缩成一维,将其看成一个1到n的序列,用a[x]=y表示第x行的点在第y列。给定n个数的一个排列,问这个序列中有多少个子区间的数恰好的连续的。相当于统计有多少个子区间[l,r]满足Max-Min==r-l,Max,Min分别为区间[l,r]的最大最小值。
- 运用分治思想,将区间[l,r]分成[l,mid],[mid+1,r]两部分,就会出现三种情况:完美子图全部在左边;完美子图全部在右边;完美子图一部分在左,一部分在右。
- 对于前两种情况属于递归子问题,第三种需将左右两边合并则出现四种情况:第一种:最大最小值均在左边,因为Max[i]-Min[i]==j-i,可以通过左端点i求出右端点j;第二种:最大最小值均在右边,同理用右端点j求出左端点i;第三种:最小值在左边,最大值在右边,i为左端点,j为右端点,则Max[j]-Min[i]==j-i =>Max[j]-j==Min[i]=i.;第四种:最小值在右边,最大值在左边,i为左端点,j为右端点,则Max[i]-Min[j]==j-i => Min[j]+j==Min[i]+i。
-
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 const int maxn=50000+10; 5 int a[maxn],Min[maxn],Max[maxn],cnt[maxn<<1]; 6 int ans=0,n; 7 void Divi(int l,int r){ 8 if(l==r){ 9 ans++; 10 return; 11 }//当只有一个点时,一定为一个完美子图,ans++ 12 int mid=(l+r)>>1; 13 Divi(l,mid);//递归左边 14 Divi(mid+1,r);//递归右边 15 Min[mid]=Max[mid]=a[mid]; 16 Min[mid+1]=Max[mid+1]=a[mid+1]; 17 for(int i=mid-1;i>=l;i--){ 18 Min[i]=min(Min[i+1],a[i]); 19 Max[i]=max(Max[i+1],a[i]); 20 } 21 for(int i=mid+2;i<=r;i++){ 22 Min[i]=min(Min[i-1],a[i]); 23 Max[i]=max(Max[i-1],a[i]); 24 }//初始化,Max,Min都是对于mid而言 25 for(int i=mid;i>=l;i--){ 26 int j=i+Max[i]-Min[i]; 27 if(j<=r&&j>mid&&Max[j]<Max[i]&&Min[i]<Min[j]) ans++; 28 }//最大最小值都在左端,判断时保证j在右端 29 for(int j=mid+1;j<=r;j++){ 30 int i=j-Max[j]+Min[j]; 31 if(i>=l&&i<=mid&&Max[i]<Max[j]&&Min[i]>Min[j]) ans++; 32 }//最大最小值都在右端,判断时i在左端 33 int j=mid+1,k=mid+1; 34 for(int i=mid;i>=l;i--){//左小右大 35 while(j<=r&&Min[j]>Min[i]){//j满足左小 36 cnt[Max[j]-j+n]++; 37 j++; 38 }//因为Max[j]-j可能为负数,所以加n 39 //不改变j的值,因为第一个while中若新的i的Min[i]不变,一定会走到当前的j,若更小,一定会走到当前的j,且可能向后走 40 while(k<j&&Max[i]>Max[k]){//若不满足右大,cnt--,因为若左大左小,前面已经计算过 41 cnt[Max[k]-k+n]--; 42 k++; 43 }//不改变k的值,因为第二个while中若新的i的Max[i]不变,一定会走到当前的k,若更大,一定会走到当前的k,且可能向后走 44 ans+=cnt[Min[i]-i+n];//因为Max[j]-j==Min[i]-i 45 } 46 while(k<j){ 47 cnt[Max[k]-k+n]--; 48 k++; 49 }//不用memset,会T掉 50 j=mid,k=mid; 51 for(int i=mid+1;i<=r;i++){ 52 while(j>=l&&Min[i]<Min[j]){ 53 cnt[Max[j]+j]++; 54 j--; 55 } 56 while(k>j&&Max[k]<Max[i]){ 57 cnt[Max[k]+k]--; 58 k--; 59 } 60 ans+=cnt[Min[i]+i]; 61 } 62 while(k>j){ 63 cnt[Max[k]+k]--; 64 k--; 65 } 66 } 67 int main(){ 68 scanf("%d",&n); 69 for(int i=1;i<=n;i++){ 70 int x,y; 71 scanf("%d%d",&x,&y); 72 a[x]=y; 73 } 74 Divi(1,n); 75 printf("%d",ans); 76 return 0; 77 }
原文地址:https://www.cnblogs.com/HZOIDJ123/p/13285477.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- java线程池(五):ForkJoinPool源码分析之一(外部提交及worker执行过程)
- JavaScript中的匿名函数、闭包和BOM
- 【Vue.js】Vue.js中的事件处理、过滤器、过渡和动画、组件的生命周期及组件之间的通信
- 树莓派基础实验18:声音传感器实验
- 树莓派基础实验19:光敏传感器实验
- 逻辑式编程还有用吗?--“三维度”逻辑编程语言的设计(2)
- git 报错解决Validate branches Cannot Create: This merge request already exists
- 树莓派基础实验20:火焰报警传感器实验
- (译)SDL编程入门(8)几何图形渲染
- Java8 dubbo 调用 Collectors.toMap代码片发生的异常(IllegalStateException: Duplicate key)
- 树莓派基础实验21:烟雾报警传感器实验
- 树莓派基础实验22:红外遥控传感器实验
- Spring的BeanUtil的copyProperties方法 慎用!!
- (译)SDL编程入门(9)视口
- (译)SDL编程入门(7)纹理加载和渲染