Codeforces 1194E. Count The Rectangles
时间:2019-09-27
本文章向大家介绍Codeforces 1194E. Count The Rectangles,主要包括Codeforces 1194E. Count The Rectangles使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
看到 $n<=5000$,直接暴力枚举左右两条竖线
然后考虑怎么计算高度在某个范围内,左端点小于等于某个值,右端点大于等于某个值的横线数量
直接用权值树状数组维护当前高度在某个区间内的横线数量
考虑先固定左边的竖线,然后枚举从左到右枚举右边的竖线,那么随着右边竖线的右移,合法的横线(右端点大于等于某个值的横线)数量只会越来越少
所以枚举右边竖线的时候同时动态维护一个指向当前最左的右端点合法的横线,然后动态维护树状数组就行了
答案也很容易计算,在固定了左右竖线的情况下,设中间有 $p$ 个最小的不可分割的矩形,那么贡献即为 $p(p+1)/2$
(枚举大矩形包含了 $k$ 小矩形,那么就是 $\sum_{k=1}^{p}(p-k+1)$)
然后因为坐标系有负数所以统一加上 $5001$ 即可
复杂度 $n^2 \log 10000$,很稳
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; typedef long long ll; inline int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); } return x*f; } const int N=10007; struct Line {//竖线 int x,l,r; Line (int _x=0,int _l=0,int _r=0) { x=_x,l=_l,r=_r; } inline bool operator < (const Line &tmp) const { return x!=tmp.x ? x<tmp.x : l<tmp.l; } }D[N]; struct Line2 {//横线 int h,l,r; Line2 (int _h=0,int _l=0,int _r=0) { h=_h,l=_l,r=_r; } }H1[N],H2[N]; inline bool cmp1(Line2 &A,Line2 &B) { return A.l!=B.l ? A.l<B.l : A.r<B.r; }//把横线按左端点排序 inline bool cmp2(Line2 &A,Line2 &B) { return A.r!=B.r ? A.r<B.r : A.l<B.l; }//按右端点排序 int n,m,md,mh; struct BIT {//树状数组 int t[N]; inline void init() { memset(t,0,sizeof(t)); } inline void add(int x,int v) { while(x<=m) t[x]+=v,x+=x&-x; } inline int ask(int x) { int res=0; while(x) res+=t[x],x-=x&-x; return res; } }T; ll Ans; int main() { n=read(); int a,b,c,d; for(int i=1;i<=n;i++) { a=read()+5001,b=read()+5001,c=read()+5001,d=read()+5001; m=max(m,max(b,d)); if(a==c) { if(b>d) swap(b,d); D[++md]=Line(a,b,d); } else { if(a>c) swap(a,c); H1[++mh]=Line2(b,a,c); H2[mh]=H1[mh]; } } sort(D+1,D+md+1); sort(H1+1,H1+mh+1,cmp1); sort(H2+1,H2+mh+1,cmp2); for(int i=1;i<=md;i++)//枚举左边的竖线 { int l=1,r=1;//动态维护指针 while(l<=mh&&H1[l].l<=D[i].x) T.add(H1[l].h,1),l++; while(r<=mh&&H2[r].r<D[i].x) T.add(H2[r].h,-1),r++; for(int j=i+1;j<=md;j++) { while(r<=mh&&H2[r].r<D[j].x) { if(H2[r].l<=D[i].x) T.add(H2[r].h,-1);//注意要判断是之前加入过的横线 r++; } if(D[i].x==D[j].x) continue;//相等不合法 int L=max(D[i].l,D[j].l),R=min(D[i].r,D[j].r); if(L>=R) continue;//相等不合法 int p=T.ask(R)-T.ask(L-1)-1; if(p<=0) continue;//构不成矩形 Ans+=1ll*p*(p+1)/2;//累计贡献 } while(r<=mh)//记得清空树状数组 { if(H2[r].l<=D[i].x) T.add(H2[r].h,-1); r++; } } printf("%lld\n",Ans); return 0; }
原文地址:https://www.cnblogs.com/LLTYYC/p/11597951.html
- Lake Counting(POJ-2386)
- Vue快速入门
- 04-树6. Huffman Codes--优先队列(堆)在哈夫曼树与哈夫曼编码上的应用
- SpringAOP实战应用
- 04-树5. File Transfer--并查集
- React快速入门
- 04-树4. Root of AVL Tree-平衡查找树AVL树的实现
- Java并发编程快速学习
- Stanford机器学习笔记-7. Machine Learning System Design
- 小程序也有“home”键盘了!
- 深度学习在文本分类中的应用
- 《大型网站技术架构》学习笔记-03案例篇
- 记一次排查DB死锁的分析
- Linux系统常用命令总结
- 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 数组属性和方法