LOJ#2307. 「NOI2017」分身术

$n \leq 100000$个点,$m \leq 100000$次询问,每次问删掉一些点后的凸包面积。

不会啦写个20暴力,其实是可以写到50的。当个计算几何板子练习。

 1 //#include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 //#include<math.h>
 5 //#include<set>
 6 //#include<queue>
 7 //#include<bitset>
 8 //#include<vector>
 9 #include<algorithm>
10 #include<stdlib.h>
11 using namespace std;
12 
13 #define LL long long
14 int qread()
15 {
16     char c; int s=0,f=1; while ((c=getchar())<'0' || c>'9') (c=='-') && (f=-1);
17     do s=s*10+c-'0'; while ((c=getchar())>='0' && c<='9'); return s*f;
18 }
19 
20 //Pay attention to '-' , LL and double of qread!!!!
21 
22 int n,m;
23 #define maxn 100011
24 int Abs(int x) {return x>0?x:-x;}
25 struct Poi
26 {
27     int x,y;
28     LL operator * (const Poi &b) const {return 1ll*x*b.y-1ll*y*b.x;}
29     Poi operator - (const Poi &b) const {return (Poi){x-b.x,y-b.y};}
30     bool operator < (const Poi &b)
31     {
32         if (x==0 && y==0) return 0;
33         if (b.x==0 && b.y==0) return 1;
34         Poi c=(Poi){0,0};
35         LL tmp=(c-(*this))*(c-b);
36         return tmp>0 || (tmp==0 && Abs(x)<Abs(b.x));
37     }
38 }p[maxn],q[maxn],sta[maxn]; int lq,top;
39 bool vis[maxn];
40 
41 int main()
42 {
43     n=qread(); m=qread();
44     for (int i=1;i<=n;i++) {p[i].x=qread(); p[i].y=qread();}
45     
46     LL s=-1;
47     int K,op;
48     while (m--)
49     {
50         memset(vis,0,sizeof(vis));
51         K=qread();
52         while (K--) vis[(qread()+s+n)%n+1]=1;
53         int my=0x3f3f3f3f,id=0; lq=top=0;
54         for (int i=1;i<=n;i++) if (!vis[i])
55         {
56             q[++lq]=p[i];
57             if (p[i].y<my) {my=p[i].y; id=lq;}
58         }
59         for (int i=1;i<=lq;i++) if (i!=id) q[i].x-=q[id].x,q[i].y-=q[id].y; q[id].x=q[id].y=0;
60         sort(q+1,q+1+lq);
61 //        for (int i=1;i<=lq;i++) cout<<q[i].x<<' '<<q[i].y<<endl;cout<<endl;
62         sta[++top]=q[lq];
63         for (int i=1;i<=lq;i++)
64         {
65             while (top>1 && (sta[top]-sta[top-1])*(q[i]-sta[top])<=0) top--;
66             sta[++top]=q[i];
67         }
68 //        for (int i=1;i<=top;i++) cout<<sta[i].x<<' '<<sta[i].y<<endl; cout<<endl;
69         s=0;
70         for (int i=1;i<top;i++) s+=sta[i]*sta[i+1];
71         printf("%lld\n",s);
72     }
73     return 0;
74 }
View Code

 

转载于:https://www.cnblogs.com/Blue233333/p/9236075.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值