标签:space std close abs click lap splay blank span
题目链接: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 }
标签:space std close abs click lap splay blank span
原文地址:https://www.cnblogs.com/xiaobuxie/p/12298494.html