【闵可夫斯基和】【莫队】codeforces1195F

题目链接:https://codeforces.com/contest/1195/problem/F

题意:给你n个凸多边形,m次询问,每次询问 [ l , r ] 区间内的凸多边形 的闵可夫斯基和 , 有多少个顶点。

首先:多个凸多边形的闵可夫斯基和其实就是多个凸多边形的边 排个序,然后首位依次相连(这个在之前的博客讲过)(闵可夫斯基和的基本)

然后我们可以看到,闵可夫斯基和有多少个顶点,相当于这些凸多边形的边有多少个不同的角度。

所以我们离散化之后,就把问题转换成给你n 个数, m个询问,每次询问 [ l , r ] 区间有多少个不同的数(都是整数)。

那么离线询问区间,并且不带修改,n是1e5 ,可以用莫队。

(也是从这题学的莫队)其实莫队就和树上启发式合并一样,本质上都是暴力,所以适用于很多情况,但是他们都是优雅的暴力,所以复杂度有保证。

莫队就是 把所有询问区间 [ l , r ] 拎出来排序,排序规则是:第一关键字:l 所属 的 块(也就是分块) , 第二关键字就是 r 。

我们可以这样看:平均下来 每个块 有 根号n 个 l , 然后 每个块 的 r 是排好序了, 所以每个块复杂度 是 O(n)的, 所以总复杂度 是 N根号N 的。

至于为什么暴力,就是因为它真的是一个个的去移动左右端点,一个个去更新啊!!!!!

然后这题还卡精度了。不过没关系,直接叉积搞他就好了。。。。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 #define eps 1e-10
 5 const int N = 1e5+9;
 6 const int M = 3e5+9;
 7 struct Point{
 8     ll x,y;
 9 }p[M];
10 struct Node{
11     double angle;
12     int id;
13     ll x,y;
14     bool operator < (const Node& b){
15         if( fabs(angle - b.angle) > eps) return angle < b.angle;
16         return x * b.y - b.x * y > 0;
17     }
18 }ang[M];
19 struct Que{
20     int id,l,r;
21     int lid;
22     bool operator < (const Que& b){
23         if( lid == b.lid) return r < b.r;
24         return lid < b.lid;
25     }
26 }q[N];
27 int a[M];
28 int L[N],R[N];
29 int num[M];
30 int ans[N];
31 int main(){
32     int n; scanf("%d",&n);
33     int cnt = 0;
34     for(int i = 1;i<=n;++i){
35         L[i] = cnt+1;
36         int k; scanf("%d",&k);
37         for(int j = 1;j<=k;++j) scanf("%lld %lld",&p[j].x,&p[j].y);
38         p[k+1] = p[1];
39         for(int j = 1;j<=k;++j){
40             ++cnt;
41             ang[cnt] =(Node){atan2(p[j+1].y - p[j].y,p[j+1].x-p[j].x),cnt,p[j+1].x-p[j].x,p[j+1].y-p[j].y};
42             //printf("%.19fwwww %lld %lld\n",ang[cnt].angle,ang[cnt].x,ang[cnt].y);
43         }
44         R[i] = cnt;
45     }
46     sort(ang+1,ang+1+cnt);
47     int tot = 0;
48     for(int i = 1;i<=cnt;){
49         a[ ang[i].id ] =  ++tot;
50         int j = i+1;
51         while( j<=cnt && fabs(ang[j].angle - ang[i].angle) < eps && ang[i].x * ang[j].y - ang[j].x * ang[i].y == 0 ){
52             a[ ang[j].id ] = tot;
53             ++j;
54         }
55         i = j;
56     }
57     int m; scanf("%d",&m);
58     int bolck = sqrt(cnt);
59     for(int i = 1;i<=m;++i){
60         int le,ri; scanf("%d %d",&le,&ri);
61         q[i].id = i;
62         q[i].l = L[le];
63         q[i].r = R[ri];
64         q[i].lid = q[i].l / bolck;
65     }
66     sort(q+1,q+1+m);
67     int nowl = 0,nowr = 0;
68     int now = 0;
69     for(int i = 1;i<=m;++i){
70         while( nowl < q[i].l ){
71             --num[ a[nowl] ];
72             if( num[ a[nowl] ] == 0 ) --now;
73             ++nowl;
74         }
75         while( nowl > q[i].l ){
76             --nowl;
77             ++num[ a[nowl] ];
78             if( num[ a[nowl] ] == 1 ) ++now;
79         }
80         while( nowr < q[i].r ){
81             ++nowr;
82             ++num[ a[nowr] ];
83             if( num[ a[nowr] ] == 1 ) ++now;
84         }
85         while( nowr > q[i].r ){
86             --num[ a[nowr] ];
87             if( num[ a[nowr] ] == 0 ) --now;
88             --nowr;
89         }
90         ans[ q[i].id ] = now;
91     }
92     for(int i = 1;i<=m;++i) printf("%d\n",ans[i]);
93     return 0;
94 }
View Code

猜你喜欢

转载自www.cnblogs.com/xiaobuxie/p/12298494.html