[hdu5033]单调队列

题意:x轴上有n棵树,询问你站在某个点的视角。从左至右,单调队列(类似凸包)维护下。我强迫症地写了个模板QAQ

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <algorithm>
  4 #include <cstdlib>
  5 #include <cstring>
  6 #include <map>
  7 #include <queue>
  8 #include <deque>
  9 #include <cmath>
 10 #include <vector>
 11 #include <ctime>
 12 #include <cctype>
 13 #include <set>
 14
 15 using namespace std;
 16
 17 #define mem0(a) memset(a, 0, sizeof(a))
 18 #define lson l, m, rt << 1
 19 #define rson m + 1, r, rt << 1 | 1
 20 #define define_m int m = (l + r) >> 1
 21 #define Rep(a, b) for(int a = 0; a < b; a++)
 22 #define lowbit(x) ((x) & (-(x)))
 23 #define constructInt4(name, a, b, c, d) name(int a = 0, int b = 0, int c = 0, int d = 0): a(a), b(b), c(c), d(d) {}
 24 #define constructInt3(name, a, b, c) name(int a = 0, int b = 0, int c = 0): a(a), b(b), c(c) {}
 25 #define constructInt2(name, a, b) name(int a = 0, int b = 0): a(a), b(b) {}
 26
 27 typedef double db;
 28 typedef long long LL;
 29 typedef pair<int, int> pii;
 30 typedef multiset<int> msi;
 31 typedef multiset<int>::iterator msii;
 32 typedef set<int> si;
 33 typedef set<int>::iterator sii;
 34 typedef vector<int> vi;
 35
 36 const int dx[8] = {1, 0, -1, 0, 1, 1, -1, -1};
 37 const int dy[8] = {0, -1, 0, 1, -1, 1, 1, -1};
 38 const int maxn = 1e5 + 7;
 39 const int maxm = 1e5 + 7;
 40 const int maxv = 1e7 + 7;
 41 const int MD = 1e9 +7;
 42 const int INF = 1e9 + 7;
 43 const double PI = acos(-1.0);
 44 const double eps = 1e-10;
 45
 46 struct Point {
 47     int x, y;
 48     bool operator < (const Point &opt) const {
 49         return x < opt.x || x == opt.x && y < opt.y;
 50     }
 51     double abs() {
 52         return sqrt((double)x * x + (double)y * y);
 53     }
 54     Point operator - (const Point &opt) const {
 55         return Point(x - opt.x, y - opt.y);
 56     }
 57     double operator * (const Point &opt) const {
 58         return (double)x * opt.x + (double)y * opt.y;
 59     }
 60     constructInt2(Point, x, y);
 61     void inp() {
 62         scanf("%d %d", &x, &y);
 63     }
 64     void outp() {
 65         printf("(%d, %d), ", x, y);
 66     }
 67 };
 68
 69 bool cmp(const pii &a, const pii &b) {
 70     return a.first < b.first;
 71 }
 72
 73 double Cross(const Point &a, const Point &b) {
 74     return (double)a.x * b.y - (double)a.y * b.x;
 75 }
 76
 77 template<class T> struct MonotoneQueue{
 78     deque<T> Q;
 79     MonotoneQueue<T>() { Q.clear(); }
 80     T back() { return Q.back(); }
 81     T back2() { if (Q.size() < 2) return T(); return *(Q.end() - 2); }
 82     T front() { return Q.front(); }
 83     void clear() { Q.clear(); }
 84     bool empty() { return Q.empty(); }
 85     void add_back(T x) { while (!empty() && !(back() - back2() < x - back2())) Q.pop_back(); Q.push_back(x); }
 86     void pop_front() { Q.pop_front(); }
 87 };
 88
 89 double toDegree(double x) { return x * 180.0 / PI; }
 90
 91 Point p[maxn], L[maxn], R[maxn];
 92 pii qry[maxn];
 93 int n, m;
 94
 95 struct Node {
 96     Point dot;
 97     bool operator < (const Node &a) const {
 98         return Cross(dot, a.dot) < eps;
 99     }
100     Node operator - (const Node &opt) const {
101         return Node(dot - opt.dot);
102     }
103     Node(Point dot = Point()): dot(dot) {}
104 };
105 MonotoneQueue<Node> DQ;
106
107 void work(Point a[]) {
108     DQ.clear();
109     DQ.add_back(p[0]);
110     int now = 1;
111     for (int i = 0; i < m; i++) {
112         while (now < n && p[now].x < qry[i].first) {
113             DQ.add_back(Node(p[now++]));
114         }
115         DQ.add_back(Node(Point(qry[i].first, 0)));
116         a[qry[i].second] = (DQ.back2() - DQ.back()).dot;
117     }
118 }
119
120 int main() {
121     //freopen("in.txt", "r", stdin);
122     int T, cas = 0;
123     cin >> T;
124     while (T--) {
125         cin >> n;
126         for (int i = 0; i < n; i++) {
127             p[i].inp();
128         }
129         sort(p, p + n);
130         cin >> m;
131         for (int i = 0, x; i < m; i++) {
132             scanf("%d", &x);
133             qry[i] = make_pair(x, i);
134         }
135         sort(qry, qry + m, cmp);
136
137         work(L);
138
139         for (int i = 0; i < n; i++) {
140             p[i].x = maxv - p[i].x;
141         }
142         sort(p, p + n);
143         for (int i = 0; i < m; i++) {
144             qry[i].first = maxv - qry[i].first;
145         }
146         sort(qry, qry + m, cmp);
147
148         work(R);
149         for (int i = 0; i < m; i++) {
150             R[i].x = -R[i].x;
151         }
152
153         printf("Case #%d:\n", ++cas);
154         for (int i = 0; i < m; i++) {
155             printf("%.10f\n", toDegree(acos(L[i] * R[i] / L[i].abs() / R[i].abs())));
156         }
157     }
158     return 0;
159 }

时间: 2024-12-15 06:56:12

[hdu5033]单调队列的相关文章

【动态规划】【单调队列】tyvj1305 最大子序和

http://blog.csdn.net/oiljt12138/article/details/51174560 单调队列优化dp #include<cstdio> #include<deque> #include<algorithm> #include<iostream> using namespace std; typedef long long ll; int n,m; ll a[300100],ans; deque<int>q; int

hdu_5884_Sort(二分+单调队列)

题目链接:hdu_5884_Sort 题意: 有n个数,每个数有个值,现在你可以选择每次K个数合并,合并的消耗为这K个数的权值和,问在合并为只有1个数的时候,总消耗不超过T的情况下,最小的K是多少 题解: 首先要选满足条件的最小K,肯定会想到二分. 然后是如何来写这个check函数的问题 我们要贪心做到使消耗最小,首先我们将所有的数排序 然后对于每次的check的mid都取最小的mid个数来合并,然后把新产生的数扔进优先队列,直到最后只剩一个数. 不过这样的做法是n*(logn)2 ,常数写的小

[Vijos 1243]生产产品(单调队列优化Dp)

Description 在经过一段时间的经营后,dd_engi的OI商店不满足于从别的供货商那里购买产品放上货架,而要开始自己生产产品了!产品的生产需要M个步骤,每一个步骤都可以在N台机器中的任何一台完成,但生产的步骤必须严格按顺序执行.由于这N台机器的性能不同,它们完成每一个步骤的所需时间也不同.机器i完成第j个步骤的时间为T[i,j].把半成品从一台机器上搬到另一台机器上也需要一定的时间K.同时,为了保证安全和产品的质量,每台机器最多只能连续完成产品的L个步骤.也就是说,如果有一台机器连续完

单调队列

先放上luogu的题目链接--滑稽窗口 然后我们再来讲单调队列 单调队列是指这样一种队列:在队列中的元素为单调递增状态或单调递减状态. 例如1 2 3 4 5和9 2 1都是单调队列,但1 2 2 3 4和4 3 4 5就不是单调队列. 但普通队列明显是维持不了单调队列的性质的. 为了维持单调队列的单调性质,我们只好想一些方法.方法就是修改队列的性质.单调队列不仅队头可以出队,队尾也可以出队. 比如说有一个单调队列是 1 3 7 8 现在突然要从队尾进来一个6如果单纯的把6插进队尾的话,那这个队

单调队列 BZOJ 2096 [Poi2010]Pilots

2096: [Poi2010]Pilots Time Limit: 30 Sec  Memory Limit: 162 MBSubmit: 819  Solved: 418[Submit][Status][Discuss] Description Tz又耍畸形了!!他要当飞行员,他拿到了一个飞行员测试难度序列,他设定了一个难度差的最大值,在序列中他想找到一个最长的子串,任意两个难度差不会超过他设定的最大值.耍畸形一个人是不行的,于是他找到了你. Input 输入:第一行两个有空格隔开的整数k(0

HDU 3706 Second My Problem First (单调队列)

题意:求给定的一个序列中最长子序列,该子序列的最大值和最小值介于m和k之间. 析:用两个单调队列来维护一个最小值,一个最大值,然后每次更新即可. 代码如下; #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <string> #include <cstdlib> #include <cmath> #include <i

codevs3327选择数字(单调队列优化)

3327 选择数字 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 钻石 Diamond 题目描述 Description 给定一行n个非负整数a[1]..a[n].现在你可以选择其中若干个数,但不能有超过k个连续的数字被选择.你的任务是使得选出的数字的和最大. 输入描述 Input Description 第一行两个整数n,k 以下n行,每行一个整数表示a[i]. 输出描述 Output Description 输出一个值表示答案. 样例输入 Sample Input 5 2

【NOIP数据结构专项】单调队列单调栈

[洛谷P1901 ]发射站 http://www.luogu.org/problem/show?pid=1901 题目描述 某地有 N 个能量发射站排成一行,每个发射站 i 都有不相同的高度 Hi,并能向两边(当 然两端的只能向一边)同时发射能量值为 Vi 的能量,并且发出的能量只被两边最近的且比 它高的发射站接收. 显然,每个发射站发来的能量有可能被 0 或 1 或 2 个其他发射站所接受,特别是为了安 全,每个发射站接收到的能量总和是我们很关心的问题.由于数据很多,现只需要你帮忙计 算出接收

【单调队列优化DP】BZOJ1855-[Scoi2010]股票交易

[题目大意] 已知第i天的股票买入价为每股APi,第i天的股票卖出价为每股BPi(数据保证对于每个i,都有APi>=BPi),第i天的一次买入至多只能购买ASi股,一次卖出至多只能卖出BSi股. 股票交易所规定在两次交易(某一天的买入或者卖出均算是一次交易)之间,至少要间隔W天,也就是说如果在第i天发生了交易,那么从第i+1天到第i+W天,均不能发生交易.同时,在任何时间,一个人的手里的股票数不能超过MaxP. 在第1天之前,有一大笔钱(可以认为钱的数目无限),没有任何股票,求T天之后最多赚到多