HDU-4533:威威猫系列故事——晒被子(线段树延迟更新+推公式)
来源:互联网 发布:vb运算符号 编辑:程序博客网 时间:2024/04/29 22:03
题目链接:点击打开链接
题目大意:
在坐标系第一象限有多个矩形,问边长为 t 的左下角坐标(0,0)的正方形覆盖的矩形面积是多少,矩形可能重叠但是无影响。
解题思路:
刚开始完全是蒙蔽的,甚至想到了用扫描线这种东西,后来发现不是矩形面积并。。。就傻了,去大佬博客学习了一发。。。
我是服气的,方法好强。具体做法是线段树中维护三个值 a,b,c。这个值跟面积有关,你可以理解为每个面积都可以表示为 a*t*t+b*t+c;
刚开始可能很懵,其实就是将矩形不断地加入线段树,不断更新维护线段树中a,b,c的值,线段树是以 t 的范围建的。
总体就是分情况讨论,每个矩形对于每个 t 值维护不同的a,b,c的值
(1) t>=max(x2,y2), 对于这些 t 值,他们的 c 直接加上(x2-x1)*(y2-y1);
(2) 如果max(x1,y1)<t<min(x2,y2)(max(x1,y1)<min(x2,y2)的前提下) 就会出现矩形的一部分在正方形中,但是并没有超过矩形上边界和右边界,这时 t 范围内增加的面积就是(t-x1)*(t-y1), 化简之后就是 t*t-(x1+y1)*t+x1*y1,那么 a,b,c分别更新1 -(x1+y1) x1*y1 就好
(3)第三种情况就是 max(min(x2,y2),max(x1,y1))<t<max(x2,y2),这里分 x2>y2 和 y2>x2 两种情况,画到图中分别是正方形超过了矩形上边界但是没有超过右边界,另外一种就是超过了右边界但是没有超过上边界。具体的公式呢可以自己推,画了图以后还是比较容易推的,需要注意的就是 维护的 a,b,c最好用 long long ,别问我咋知道的。。。
细节要注意以下边界,具体看代码吧,
#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <cmath>#include <vector>#include <queue>#include <map>#include <algorithm>#include <stack>#include <set>#include <functional>#define rank ra#define lson rt<<1#define rson rt<<1|1#define pb push_back#define hash haha#define double intusing namespace std;typedef long long ll;const int N=200000;int n,m;ll ans;struct node{ int l,r,mid; ll a,b,c; //long long 型 int lazy;}t[N<<2];void build(int l,int r,int rt){ int mid=(l+r)>>1; t[rt].l=l;t[rt].r=r; t[rt].mid=mid; t[rt].a=t[rt].b=t[rt].c=0; t[rt].lazy=0; if(l==r) return ; build(l,mid,lson); build(mid+1,r,rson);}void pushdown(int rt){ if(t[rt].lazy) //延迟更新 { t[lson].a+=t[rt].a; t[rson].a+=t[rt].a; t[lson].b+=t[rt].b; t[rson].b+=t[rt].b; t[lson].c+=t[rt].c; t[rson].c+=t[rt].c; t[rt].lazy=0; t[lson].lazy=t[rson].lazy=1; t[rt].a=t[rt].b=t[rt].c=0; }}void update(int l,int r,ll a,ll b,ll c,int rt) //更新a,b,c,的值{ if(l<=t[rt].l&&t[rt].r<=r) { t[rt].lazy=1; t[rt].a+=a; t[rt].b+=b; t[rt].c+=c; return ; } pushdown(rt); if(l<=t[rt].mid) update(l,r,a,b,c,lson); if(r>t[rt].mid) update(l,r,a,b,c,rson);}void query(int k,int rt) //单点查询{ if(t[rt].l==t[rt].r) { ans+=(t[rt].a*k*k+t[rt].b*k+t[rt].c); return ; } pushdown(rt); if(k<=t[rt].mid) query(k,lson); if(k>t[rt].mid) query(k,rson);}int main(){ int QAQ; scanf("%d",&QAQ); while(QAQ--) { build(1,200000,1); scanf("%d",&n); ll x1,y1,x2,y2; for(int i=0;i<n;i++) { scanf("%lld%lld%lld%lld",&x1,&y1,&x2,&y2); update(max(x2,y2),N,0,0,(x2-x1)*(y2-y1),1); //分别对应三种情况 注意边界 if(max(x1,y1)<min(x2,y2)) update(max(x1,y1),min(x2,y2)-1,1,-(x1+y1),x1*y1,1); int k1=max(min(x2,y2),max(x1,y1)),k2=max(x2,y2); if(x2>y2) update(k1,k2-1,0,(y2-y1),-x1*(y2-y1),1); if(y2>x2) update(k1,k2-1,0,(x2-x1),-y1*(x2-x1),1); } scanf("%d",&m); int k; for(int i=0;i<m;i++) { ans=0; scanf("%d",&k); //对于每次查询输出答案 query(k,1); cout<<ans<<endl; } }}
- HDU-4533:威威猫系列故事——晒被子(线段树延迟更新+推公式)
- HDU 4533 威威猫系列故事――晒被子(线段树区间更新+分情况推公式)
- hdu 4533 威威猫系列故事——晒被子(线段树 成端更新)
- hdu 4533 威威猫系列故事——晒被子(成段更新)
- HDU 4533 威威猫系列故事——晒被子
- Hdu 4533 威威猫系列故事——晒被子
- hdu 4533 威威猫系列故事——晒被子
- hdu 4533 威威猫系列故事——晒被子
- HDU 4533 威威猫系列故事――晒被子 (线段树)
- hdu 4533 威威猫系列故事——晒被子(两种方法)
- 威威猫系列故事——晒被子
- HDOJ 4533 威威猫系列故事——晒被子
- hdu-4533-威威猫系列故事――晒被子----
- hdu 4533 威威猫系列故事――晒被子(二重等差数列+差分前缀和)
- hdu4533-威威猫系列故事——晒被子
- hdu4533 威威猫系列故事——晒被子
- HDU 4525 威威猫系列故事——吃鸡腿(水题,合并递推公式就行)
- hud 2013腾讯编程马拉松 威威猫系列故事——晒被子
- 2017-08-17
- HDU 1430 魔板
- 八大机器学习框架对比及Tensorflow的优势
- 一些大咖的BLOG
- 数据结构与算法_合并两个排好顺序的链表或数组
- HDU-4533:威威猫系列故事——晒被子(线段树延迟更新+推公式)
- python返回指定目录下指定的文件或文件夹
- INT_MAX和INT_MIN注意事项
- 如何关掉Win7下运行程序时候安全提示对话框
- Spark2.1.0完全分布式环境搭建
- 原生JS实现瀑布流效果
- Java基础---字符流
- try catch finally简介
- DataGridView 显示值 真值