一道好题。想了好久没想出来,只是觉得总要二分独立处理矩形。感觉自己在把问题转化为数学公式以及分解问题的方面的能力很不足。

http://blog.csdn.net/wh2124335/article/details/8739097

解题思路:

考虑每次询问t,对于单一矩形的面积的计算方法~
对于询问t。计算如图矩形所被包含的面积可以用矩形面积S[TCFI]-S[TJGI],而S[TCFI]=(t-Fx)*(t-Fy);S[TJGI]=(t-Gx)*(t-Gy)
换句话说就是用[T和矩形左下角的点形成的面积]减去[T和矩形右下角形成的矩形面积]就是这个矩形被包含的面积!
 
下面来看一个类似的情况:
对于这次询问t。当前矩形被包涵的面积是S[TLFI]-S[TLEK]。即[T和矩形左下角点形成的面积]减去[T和矩形左上角点形成的矩形的面积]
 
那么对于矩形被包含进(t,t)范围是什么情况呢?
这时候的面积是EHGF的面积,但我们还想计算这个面积时和T有关。仿照前面的讨论,发现S[EHGF]不就是S[TLFI]-S[TLEN]-S[TMGI]+S[TMHN]么?
换句话描述,就是[T和矩形左下角点形成的矩形面积]减去[T和矩形左上角点形成的矩形面积]减去[T和矩形右下角点形成的矩形面积]加上[T和矩形右上角点形成的矩形面积]
 
那么我们得到了如下算法:
输入询问t
sum=0
遍历所有矩形的四个顶点
   如果该顶点在(0,0)-(t,t)的范围内
      如果当前顶点是它所在矩形的左上角或右下角的点那么sum+=[(t,t)和该点形成的矩形的面积]
      否则sum-=[(t,t)和该点形成的矩形的面积]
返回sum
 
对于这题目的数据来说时间复杂度肯定是不够的,我们要想办法优化它。。。
 
观察我们计算[T和当前点形成的矩形面积]时的方法:
假设当前点坐标是(x,y)
那么S=(t-x)*(t-y)
我们可以将上式展开:S=t*t-t(x+y)+xy
我们可不可以将上式分成的三部分分别求和呢?答案是可以的!
 
那么我们可以将所有矩形左下角和右上角的点分到一组a(因为它们和T形成的矩形面积都是做“加”运算),把左上角和右下角的点分到一组b(因为它们和T形成的矩形面积都是做“减”运算)
 
那么结果可以写成sigma[a中在(t,t)范围内的点和T形成的矩形面积]-sigma[b在(t,t)范围内的点和T形成的矩形面积]
 
很容易想到,我们将a,b中的点分别按max(x,y)排序。然后正确的算法已经呼之欲出了!
对于每次询问t,我们二分找到它在a,b中的位置n,m(即max(x,y)恰好不超过t的最大的下标,a,b都是从1开始编号)
答案不就是
Sum(Sa)-Sum(Sb)
=sigma[t*t-t*(x+y)+xy](a中点)-sigma[t*t-t*(x+y)+xy](b中点)
=[sigma(t*t)-sigma(x+y)+sigma(xy)](a中点)-[sigma(t*t)-sigma(x+y)+sigma(xy)](b中点)
 
计算sigma(t*t)只要t*t乘个数(对于a是n,对于b是m)即可!
计算sigma(x+y)和sigma(xy)只要预处理一下即可!
 
现在算法如下:
 
检查所有矩形的四个顶点
        如果是左下角或是右上角的点那么放到a的末尾
        否则放到b的末尾
将a,b中的所有点按max(x,y)排序
定义suma,sumb表示a、b的点中下标1到下标i的所有点的x+y和
定义suma_mul,sumb_mul表示a、b的点中下标1到下标i的所有点的x*y和
循环 i=1 到 2*N 
        suma[i]=suma[i-1]+a[i].x+a[i].y
        sumb[i]=sumb[i-1]+b[i].x+b[i].y
        suma_mul[i]=suma_mul[i-1]+a[i].x*a[i].y
        sumb_mul[i]=sumb_mul[i-1]+b[i].y*b[i].y
对于每次询问t
        二分找到在a,b中max(x,y)恰好不超过t的下标n,m
        输出答案(t*t*n-t*suma[n]+suma_mum[n])-(t*t*m-t*sumb[m]+sumb_mul[m])

 

看过后敲代码不难。注意以后在涉及计算方面要把问题往数学公式方面靠近。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define LL __int64
using namespace std;
const int N= 20100; struct Point{
int x,y,qc;
Point (){}
Point (int x1,int y1){
x=x1,y=y1;
qc=max(x,y);
}
}a[N*2],b[N*2];
int n; LL aad[N*2],aam[N*2];
LL bad[N*2],bam[N*2]; bool cmp(Point a,Point b){
if(a.qc<b.qc ) return true;
return false;
} int bin(Point *s,int t){
int l=0,r=2*n-1;
int ans=-1;
while(l<=r){
int m=(l+r)>>1;
if(s[m].qc<=t){
ans=m;
l=m+1;
}
else r=m-1;
}
return ans;
} int main(){
int T,x1,y1,x2,y2,cnta,cntb,m,t;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
cnta=cntb=0;
for(int i=0;i<n;i++){
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
a[cnta++]=Point(x1,y1);
a[cnta++]=Point(x2,y2);
b[cntb++]=Point(x1,y2);
b[cntb++]=Point(x2,y1);
}
sort(a,a+2*n,cmp);
sort(b,b+2*n,cmp);
aad[0]=a[0].x+a[0].y; aam[0]=a[0].x*a[0].y;
bad[0]=b[0].x+b[0].y; bam[0]=b[0].x*b[0].y;
for(int i=1;i<n*2;i++){
aad[i]=aad[i-1]+a[i].x+a[i].y;
aam[i]=aam[i-1]+(LL)a[i].x*(LL)a[i].y;
bad[i]=bad[i-1]+b[i].x+b[i].y;
bam[i]=bam[i-1]+(LL)b[i].x*(LL)b[i].y;
}
scanf("%d",&m);
LL ans;
while(m--){
scanf("%d",&t);
int a1=bin(a,t),b1=bin(b,t);
if(a1==-1)
puts("0");
else if(b1==-1){
ans=(LL)(a1+1)*(LL)t*(LL)t-aad[a1]*(LL)t+aam[a1];
printf("%I64d\n",ans);
}
else{
ans=(LL)(a1+1)*(LL)t*(LL)t-aad[a1]*(LL)t+aam[a1]-((LL)(b1+1)*(LL)t*(LL)t-bad[b1]*(LL)t+bam[b1]);
printf("%I64d\n",ans);
}
}
}
return 0;
}

  

HDU 4533的更多相关文章

  1. hdu 4533 线段树(问题转化+)

    威威猫系列故事——晒被子 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Tot ...

  2. HDU 4533 威威猫系列故事——晒被子

    题目链接 扫描线可做,然后当时比赛后问虎哥,他说可以标记,然后拖了很久,今天从早上折腾到晚上,终于把两种情况写出来,分析太弱.改天扫描线,再来一次. 被子如果被y = x 穿过,可以分成两部分,上和下 ...

  3. 线段树总结 (转载 里面有扫描线类 还有NotOnlySuccess线段树大神的地址)

    转载自:http://blog.csdn.net/shiqi_614/article/details/8228102 之前做了些线段树相关的题目,开学一段时间后,想着把它整理下,完成了大牛NotOnl ...

  4. HDOJ 2111. Saving HDU 贪心 结构体排序

    Saving HDU Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  5. 【HDU 3037】Saving Beans Lucas定理模板

    http://acm.hdu.edu.cn/showproblem.php?pid=3037 Lucas定理模板. 现在才写,noip滚粗前兆QAQ #include<cstdio> #i ...

  6. hdu 4859 海岸线 Bestcoder Round 1

    http://acm.hdu.edu.cn/showproblem.php?pid=4859 题目大意: 在一个矩形周围都是海,这个矩形中有陆地,深海和浅海.浅海是可以填成陆地的. 求最多有多少条方格 ...

  7. HDU 4569 Special equations(取模)

    Special equations Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u S ...

  8. HDU 4006The kth great number(K大数 +小顶堆)

    The kth great number Time Limit:1000MS     Memory Limit:65768KB     64bit IO Format:%I64d & %I64 ...

  9. HDU 1796How many integers can you find(容斥原理)

    How many integers can you find Time Limit:5000MS     Memory Limit:32768KB     64bit IO Format:%I64d ...

随机推荐

  1. MySQL的DML和DQL 增删改查

    DML和DQL   增删改查 SELECT * FROM grade --新增 insert -- 向年级表中新增3条数据INSERT INTO grade(gradeID,gradeName) VA ...

  2. 10.Nodes and Bindings

    节点数据绑定 节点是构成Ventuz场景的基本元素.每个节点既属于图层.也属于层级或内容.既可以在图层编辑器,也可以在层级编辑器或内容编辑器中编辑. 内容节点包括资产描述(如材质.xml文件等).数字 ...

  3. 依存分析 Dependency Parsing

    依存分析 Dependency Parsing 句子成分依存分析主要分为两种:句法级别的和语义级别的 依存句法分析 syntactic dependency parsing 语义依存分词 semant ...

  4. 【MySQL】RPM包安装

    操作系统:Red Hat Enterprise Linux Server release 6.5 Mysql安装包:MySQL-5.6.35-1.linux_glibc2.5.x86_64.rpm-b ...

  5. html5——多媒体(三)

    自定义进度条 1.video标签是内联块,可以设置宽高,但是需要用大盒子将其包裹起来进行定位 2.小盒子设计成进度条样式,并进行定位 3.进度条样式中的特殊按钮可以用web字体 4.通过点击实现视频的 ...

  6. iOS开发中如何实现同步、异步、GET、POST等请求实操演示!

    1.同步请求可以从因特网请求数据,一旦发送同步请求,程序将停止用户交互,直至服务器返回数据完成,才可以进行下一步操作, 2.异步请求不会阻塞主线程,而会建立一个新的线程来操作,用户发出异步请求后,依然 ...

  7. node里读取命令行参数

    一.process.env process.env属性返回一个包含用户环境信息的对象. 最常见的需求,前端需要根据不同的环境(dev,prd),来调用不同的后端接口.如果用webpack,是这么做的: ...

  8. 阿里P8架构师详解Java性能调优策略

    一.性能测试 Ⅰ.测试方法 微基准性能测试 可以精准定位到某个模块或者某个方法的性能问题,例如对比一个方法使用同步实现和非同步实现的性能差异 宏基准性能测试 宏基准性能测试是一个综合测试,需要考虑到测 ...

  9. JS DOM节点(当前标签和同级、父级、子级..之间的关系)

    1. 通过顶层document节点获取    1) document.getElementById(elementId) //根据id获得    2) document.getElementsByNa ...

  10. 【源码阅读】opencv中opencl版本的dft函数的实现细节

    1.函数声明 opencv-3.4.3\modules\core\include\opencv2\core.hpp:2157 CV_EXPORTS_W void dft(InputArray src, ...