HDU-4533 威威猫系列故事——晒被子 数学分析

2023-10-15 01:20

本文主要是介绍HDU-4533 威威猫系列故事——晒被子 数学分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

看了下面这篇文章后就恍然大悟了,不得不佩服解题方法的精妙之处。

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

题目大意:

 

在第一象限中给出若干矩形(点范围1e5,矩形个数20000),现在给出一些询问(次数20000),每次询问给出一个整数t,问在(0,0)到(t,t)范围的矩形面积和。

解题思路:

考虑每次询问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 <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;typedef long long int64;
int N, M;
int64 saxay[20005*2], saxmy[20005*2];
int64 sbxay[20005*2], sbxmy[20005*2];struct Node {int64 x, y;void set(int64 cx, int64 cy) {x = cx, y = cy;    }bool operator < (const Node & t) const {return max(x, y) < max(t.x, t.y); // 按照被覆盖的时间排序
    }bool operator < (int t) const {return max(x, y) < t;}
}a[20005*2], b[20005*2];void insert(int i) {int64 x1, y1, x2, y2;scanf("%I64d %I64d %I64d %I64d", &x1, &y1, &x2, &y2);a[i].set(x1, y1), a[i+1].set(x2, y2);b[i].set(x1, y2), b[i+1].set(x2, y1);
}void deal() {for (int i = 1; i <= N*2; ++i) {saxay[i] = saxay[i-1] + a[i].x + a[i].y;saxmy[i] = saxmy[i-1] + a[i].x * a[i].y;sbxay[i] = sbxay[i-1] + b[i].x + b[i].y;sbxmy[i] = sbxmy[i-1] + b[i].x * b[i].y;}
}int64 query(int ti) {int64 ret = 0;int pa = lower_bound(a+1, a+N*2+1, ti) - a - 1;int pb = lower_bound(b+1, b+N*2+1, ti) - b - 1;// pa, pb分别指向ti覆盖到了的点的位置// printf("pa = %d, pb = %d\n", pa, pb);if (pa != 0)ret += 1LL*pa*ti*ti-ti*saxay[pa]+saxmy[pa];if (pb != 0)ret -= 1LL*pb*ti*ti-ti*sbxay[pb]+sbxmy[pb];return ret;
}int main() {int T;scanf("%d", &T);while (T--) {scanf("%d", &N);for (int i = 0; i < N; ++i) {insert(i*2+1);}sort(a+1, a+1+2*N), sort(b+1, b+1+2*N);deal();scanf("%d", &M);while (M--) {int ti;scanf("%d", &ti);printf("%I64d\n", query(ti));    }}return 0;    
}

 

转载于:https://www.cnblogs.com/Lyush/archive/2013/03/30/2990404.html

这篇关于HDU-4533 威威猫系列故事——晒被子 数学分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/214457

相关文章

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

usaco 1.3 Mixing Milk (结构体排序 qsort) and hdu 2020(sort)

到了这题学会了结构体排序 于是回去修改了 1.2 milking cows 的算法~ 结构体排序核心: 1.结构体定义 struct Milk{int price;int milks;}milk[5000]; 2.自定义的比较函数,若返回值为正,qsort 函数判定a>b ;为负,a<b;为0,a==b; int milkcmp(const void *va,c

poj 3974 and hdu 3068 最长回文串的O(n)解法(Manacher算法)

求一段字符串中的最长回文串。 因为数据量比较大,用原来的O(n^2)会爆。 小白上的O(n^2)解法代码:TLE啦~ #include<stdio.h>#include<string.h>const int Maxn = 1000000;char s[Maxn];int main(){char e[] = {"END"};while(scanf("%s", s) != EO

hdu 2093 考试排名(sscanf)

模拟题。 直接从教程里拉解析。 因为表格里的数据格式不统一。有时候有"()",有时候又没有。而它也不会给我们提示。 这种情况下,就只能它它们统一看作字符串来处理了。现在就请出我们的主角sscanf()! sscanf 语法: #include int sscanf( const char *buffer, const char *format, ... ); 函数sscanf()和

hdu 2602 and poj 3624(01背包)

01背包的模板题。 hdu2602代码: #include<stdio.h>#include<string.h>const int MaxN = 1001;int max(int a, int b){return a > b ? a : b;}int w[MaxN];int v[MaxN];int dp[MaxN];int main(){int T;int N, V;s

科研绘图系列:R语言扩展物种堆积图(Extended Stacked Barplot)

介绍 R语言的扩展物种堆积图是一种数据可视化工具,它不仅展示了物种的堆积结果,还整合了不同样本分组之间的差异性分析结果。这种图形表示方法能够直观地比较不同物种在各个分组中的显著性差异,为研究者提供了一种有效的数据解读方式。 加载R包 knitr::opts_chunk$set(warning = F, message = F)library(tidyverse)library(phyl

hdu 1754 I Hate It(线段树,单点更新,区间最值)

题意是求一个线段中的最大数。 线段树的模板题,试用了一下交大的模板。效率有点略低。 代码: #include <stdio.h>#include <string.h>#define TREE_SIZE (1 << (20))//const int TREE_SIZE = 200000 + 10;int max(int a, int b){return a > b ? a :

hdu 1166 敌兵布阵(树状数组 or 线段树)

题意是求一个线段的和,在线段上可以进行加减的修改。 树状数组的模板题。 代码: #include <stdio.h>#include <string.h>const int maxn = 50000 + 1;int c[maxn];int n;int lowbit(int x){return x & -x;}void add(int x, int num){while

hdu 3790 (单源最短路dijkstra)

题意: 每条边都有长度d 和花费p,给你起点s 终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。 解析: 考察对dijkstra的理解。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstrin

hdu 2489 (dfs枚举 + prim)

题意: 对于一棵顶点和边都有权值的树,使用下面的等式来计算Ratio 给定一个n 个顶点的完全图及它所有顶点和边的权值,找到一个该图含有m 个顶点的子图,并且让这个子图的Ratio 值在所有m 个顶点的树中最小。 解析: 因为数据量不大,先用dfs枚举搭配出m个子节点,算出点和,然后套个prim算出边和,每次比较大小即可。 dfs没有写好,A的老泪纵横。 错在把index在d