[POI 2008][BZOJ 1132]Tro

这题我真是无能为力了

这题的做法还是挺简单的

枚举左下角的点做为原点,把其余点按极角排序    PS.是作为原点,如枚举到 k 时,对于所有 p[i] (包括p[k]) p[i]-=p[k] (此处为向量减法)

排序后满足 i<j 的两个向量 p[i] 和 p[j] 的叉积都是正数了

ΣΣp[i]×p[j] = ΣΣ(p[i].x*p[j].y-p[i].y*p[j].x) = Σ(p[i].x*Σp[j].y)-Σ(p[i].y*Σp[j].x)

计算叉积和的复杂度就从 O(n2) 降为了 O(n)

再加上枚举和排序的复杂度,总复杂度就是 O(n2logn)

但是我的代码似乎被 BZOJ 讨厌了%>_<%

本地测都是 A 的,校内 OJ 也 A 了,但BZOJ一交上去秒 WA 啊,55555555

求大爷指导……

这是错误的代码,求教做人

 1 #include <cstdio>
 2 #include <algorithm>
 3 const int size=5000;
 4 typedef struct point vector;
 5 typedef long long llint;
 6
 7 namespace IOspace
 8 {
 9     inline int getint()
10     {
11         register int num=0;
12         register char ch;
13         do ch=getchar(); while (ch<‘0‘ || ch>‘9‘);
14         do num=num*10+ch-‘0‘, ch=getchar(); while (ch>=‘0‘ && ch<=‘9‘);
15         return num;
16     }
17     inline void putint(llint num, char ch=‘\n‘)
18     {
19         char stack[20];
20         register int top=0;
21         if (num==0) stack[top=1]=‘0‘;
22         for ( ;num;num/=10) stack[++top]=num%10+‘0‘;
23         for ( ;top;top--) putchar(stack[top]);
24         if (ch) putchar(ch);
25     }
26 }
27
28 struct point
29 {
30     llint x, y;
31     inline point() {}
32     inline point(llint _x, llint _y):x(_x), y(_y) {}
33     inline vector & operator += (vector v) {x+=v.x; y+=v.y; return *this;}
34     inline vector & operator -= (vector v) {x-=v.x; y-=v.y; return *this;}
35 };
36 point p[size];
37 inline llint operator * (vector a, vector b) {return a.x*b.y-a.y*b.x;}
38 inline bool operator < (point a, point b) {return a*b>0;}
39 inline void swap(point & a, point & b) {point t=a; a=b; b=t;}
40
41 int N;
42 inline llint count(int);
43
44 int main()
45 {
46     llint ans=0;
47
48     N=IOspace::getint();
49     for (int i=1;i<=N;i++) p[i].x=IOspace::getint(), p[i].y=IOspace::getint();
50
51     for (int i=N;i>=1;i--) ans+=count(i);
52
53     bool b=ans&1LL;
54     IOspace::putint(ans>>1LL, ‘.‘);
55     IOspace::putint(b?5:0);
56
57     return 0;
58 }
59 inline llint count(int n)
60 {
61     llint ret=0;
62
63     int k=1;
64     for (int i=1;i<=n;i++)
65         if (p[i].x<p[k].x || p[i].x==p[k].x && p[i].y<p[k].y)
66             k=i;
67     swap(p[k], p[n]);
68
69     for (int i=1;i<=n;i++) p[i]-=p[n];
70
71     std::sort(p+1, p+n);
72
73     vector s(0, 0);
74     for (int i=1;i<=n;i++)
75     {
76         ret+=s*p[i];
77         s+=p[i];
78     }
79
80     return ret;
81 }

欲哭无泪的本傻系列

我再把正确的放上来,帮助理解题解:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 using namespace std;
 5
 6 #define maxn 30010
 7 typedef long long ll;
 8 struct xllend3
 9 {
10     int x,y;
11 } orz[maxn];
12
13 int n,m;
14 ll ans;
15
16 bool cmp(const xllend3 &a,const xllend3 &b)
17 {
18     return a.x*b.y>a.y*b.x;
19 }
20 ll orzhzw(int n)
21 {
22     int i=0;
23     for (int j=0;j<n;j++)
24     if (orz[j].x<orz[i].x||(orz[j].x==orz[i].x && orz[j].y<orz[i].y))
25         i=j;
26     swap(orz[i],orz[n-1]);
27     for (int i=0;i<n-1;i++)
28         orz[i].x-=orz[n-1].x,orz[i].y-=orz[n-1].y;
29     sort(orz,orz+n-1,cmp);
30     ll gui=0;
31     ll sx=0,sy=0;
32     for (int i=n-2;i>=0;i--)
33     {
34         gui+=(ll)orz[i].x*sy-(ll)orz[i].y*sx;
35         sx+=orz[i].x;
36         sy+=orz[i].y;
37     }
38     return gui;
39 }
40
41 int main()
42 {
43     scanf("%d",&n);
44     for (int i=0;i<n;i++)    scanf("%d%d",&orz[i].x,&orz[i].y);
45     for (int i=n;i>2;i--)    ans+=orzhzw(i);
46     cout<<ans/2;
47     if (ans&1)    cout<<".5"<<endl;else cout<<".0"<<endl;
48     return 0;
49 }

Orz mxh1999

[POI 2008][BZOJ 1132]Tro

时间: 2024-07-29 04:49:48

[POI 2008][BZOJ 1132]Tro的相关文章

[POI 2008]Mafia

这题目写了我好长时间,但还是几乎(不要在意细节)一遍 A 了喵~ 据说有代码奇短的,Orz 思路巧妙的大爷 想我这种 Brute Force 写写的傻 X 真是代码量飞起来了耶,喵~ 如果把每个人看成点,每个人要 kill 的人向此人连出一条有向边,那么每个点仅有一条出边和一条入边 经验告诉我们,这就是 环+内向图 的节奏 经验又告诉我,处理这种图要么先暴力搞环,再搞挂在环上的树.要么先搞树,再弄环. 此题显然是后者 环+内向图只需要用 bfs 就可以搞出来了,看到写 tarjan 的真是 Or

BZOJ 1132 POI 2008 Tro 计算几何

题目大意:给出平面上的一些点,问这些点中的任意三个点组成的三角形的面积和是多少. 思路:看数据范围只算法系列.由于每个三角形有三个顶点,因此暴力的话应该是O(n^3)的时间复杂度,很明显超时了,但是我们只需要将它优化到O(n^2logn)就可以解决了. 好吧,剩下的随便猜一猜,比如O(n^2)的枚举,然后剩下的logn什么也干不了... 再比如O(n)的枚举,然后剩下O(nlogn)排序... 好像有戏啊.. 枚举每一个点,计算以这个点为坐标原点,在第一象限的所有点与原点组成的三角形的面积和.计

BZOJ 1132 [POI2008]Tro(极角排序)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1132 [题目大意] 平面上有N个点. 求出所有以这N个点为顶点的三角形的面积和(N<=3000) [题解] 我们发现直接枚举三个点计算会造成很大部分的叉积重复被计算, 因此我们枚举i,计算pj和pi点差的后缀和,我们发现对于固定边ij, 其与后面的枚举量相关贡献就为pj-pi和点差后缀和的叉积. 因此我们针对每个i进行后面数据的极角排序,O(n)计算与i相关的所有答案贡献. [代码]

bzoj 1132 POI2008 Tro

大水题=_=,可我想复杂了…… 很裸的暴力,就是加了个小优化…… 叉积求面积 :abs(xi*yj - yi*xj) 所以去掉绝对值,把 xi 和 xj 提出来就可以求和了 去绝对值加个极角排序,每次把最左边的点当成原点,然后剩下的排序,接着枚举第二个点,求叉积之和…… 坐标都是整数,用long long,最后再除2 上代码: #include <cstdio> #include <cstring> #include <cstdlib> #include <ios

BZOJ 1132 POI2008 Tro 计算几何

题目大意:给定平面上的一些点,求这些点能组成的所有三角形的面积之和 首先我们枚举每一个点 以这个点为原点建立平面直角坐标系 然后将第一.四象限和x.y轴正半轴上的点按照斜率排序 枚举第二个和第三个点 这样做是O(n^3)的 肯定超时 但是我们发现了什么? 对于每个点k 它对答案的贡献为: (x1*yk-y1*xk)+(x2*yk-y2*xk)+...+(x_(k-1)*yk-y_(k-1)*xk) =(x1+x2+...+x_(k-1))*yk-(y1+y2+...+y_(k-1))*xk 于是

bzoj 1112 poi 2008 砖块

这滞胀题调了两天了... 好愚蠢的错误啊... 其实这道题思维比较简单,就是利用treap进行维护(有人说线段树好写,表示treap真心很模板) 就是枚举所有长度为k的区间,查出中位数,计算代价即可. (根据绝对值不等式的几何意义,中位数一定是最优解) 而维护长度为k的区间也很简单,就是首先把前k个扔到树上,然后每次把新来的插入,把最前面的一个删除即可 至于求中位数,简直就是基础操作嘛 关键在于...代价怎么算? 显然我们不能把所有数枚举出来挨个加减,这样会T飞的... 所以我们考虑直接在tre

[POI 2008&amp;洛谷P3467]PLA-Postering题解(单调栈)

Description Byteburg市东边的建筑都是以旧结构形式建造的:建筑互相紧挨着,之间没有空间.它们共同形成了一条长长的,从东向西延伸的建筑物链(建筑物的高度不一). Byteburg市的市长Byteasar,决定将这个建筑物链的一侧用海报覆盖住.并且想用最少的海报数量,海报是矩形的. 海报与海报之间不能重叠,但是可以相互挨着(即它们具有公共边),每一个海报都必须贴近墙并且建筑物链的整个一侧必须被覆盖(意思是:海报需要将一侧全部覆盖,并且不能超出建筑物链) 输入格式:第一行为一个整数n

bzoj 1132 几何

思路:我刚开始算三角形的方法是原点叉积三条边,然后计算每条边向量积的贡献,但是对于同一条线上的点 有时候没有办法抵消掉..... 看网上的思路是对于一个三角形的面积通过两条边的叉积获得,然后枚举一个点,排序去掉公式的绝对值,记录 后缀和进行计算... 看的这篇博客.. https://www.cnblogs.com/GXZlegend/p/7509699.html #include<bits/stdc++.h> #define LL long long #define fi first #de

解题:POI 2008 Subdivision of Kingdom

题面 还可以这么搜......学到了(PoPoQQQ orz) 我们最朴素的做法是枚举所有状态(当然可以剪,剪完最终实际状态量也是$C_{26}^{13}$的),然后每次$O(n)$扫一遍判断,大概会T炸,考虑优化 我们先预处理每个状态中$1$的数目和连边的状态,然后压缩状态初始让一边集合为空,一边集合为全集,这样每次从已有的点的前面$\frac{n}{2}$个点中枚举一个加入另一边,就可以边搜边更新边数而不用最后$O(n)$检查了.另一个问题是数组可能非常大,这里我们可以把状态拆成前后两半,然