好多HDU的题,我想死。
求从左到右字典序最小上凸壳,注意这个题不能选多个重点。
A C C o d e \mathcal AC \ Code AC Code
#include
#define maxn 200005
#define LL long long
#define Ct const
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--)
using namespace std;
int n;
#define Pt Point
struct Pt{
LL x,y;
Pt(Ct LL &x=0,Ct LL &y=0):x(x),y(y){}
Pt operator +(Ct Pt &B)Ct{ return Pt(x + B.x , y + B.y); }
Pt operator -(Ct Pt &B)Ct{ return Pt(x - B.x , y - B.y); }
LL operator *(Ct Pt &B)Ct{ return x * B.y - y * B.x; }
}P[maxn];
int c[maxn];
bool cmp(const int &u,const int &v){ return P[u].x == P[v].x ? P[u].y > P[v].y : P[u].x < P[v].x; }
int q[maxn],R;
int main(){
int T;
for(scanf("%d",&T);T--;){
scanf("%d",&n);
rep(i,1,n) scanf("%lld%lld",&P[i].x,&P[i].y),c[i]=i;
stable_sort(c+1,c+1+n,cmp);
q[R=0] = 1;
rep(i,2,n){
int u=c[i];
if(P[u].x == P[c[i-1]].x && P[u].y == P[c[i-1]].y)
continue;
for(;R>=1 && (
(P[q[R]] - P[q[R-1]]) * (P[u] - P[q[R-1]]) > 0
||
((P[q[R]] - P[q[R-1]]) * (P[u] - P[q[R-1]]) == 0 && u < q[R])
)
;)
R--;
q[++R] = u;
}
rep(i,0,R) printf("%d%c",q[i]," \n"[i==R]);
}
}
求 n n n个点中选三个点的最大三角形面积。
首先存在一个最大三角形三个点都在凸包上。
求出凸包后有 O ( n 2 ) O(n^2) O(n2)的旋转卡壳和 O ( n 3 ) O(n^3) O(n3)的暴力枚举算法。
但是他们都能过。
这是因为这道题有一个性质是 x , y ∈ N ∧ − 1 e 4 ≤ x , y ≤ 1 e 4 x,y \in \N \wedge -1e4 \leq x , y \leq 1e4 x,y∈N∧−1e4≤x,y≤1e4
设 C = 1 e 4 C = 1e4 C=1e4
有一个结论就是凸包上的点数上界是 O ( C 2 3 ) O(C^\frac 23) O(C32)(期望点数是 O ( log C ) O(\log C) O(logC)的)
首先很多构造凸包的想法都是 O ( C 1 2 ) O(C^\frac 12) O(C21)的,
证明思路应该是有效的斜率只有 O ( C 2 3 ) O(C^\frac 23) O(C32)种(具体证明应该和 S t e r n − B r o c o t T r e e Stern-Brocot\ Tree Stern−Brocot Tree有关,也就是和最简分数有关其实就是我不会),这是答案的上界。
然后这里给出一个构造:
造一个 x 2 + y 2 ≤ C 2 x^2 + y^2 \leq C^2 x2+y2≤C2的圆,把圆内所有顶点造个凸包,容易发现这个凸包的点数就是 O ( n 2 3 ) O(n ^ \frac 23) O(n32)级别的。
这东西怎么网上一点提示都没有啊啊啊啊啊啊啊啊啊连CF出题人都敷衍了事这莫非是什么离谱的openproblem吗
A C C o d e \mathcal AC \ Code AC Code
#include
#define maxn 50005
#define LL long long
#define Ct const
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--)
using namespace std;
int n;
#define Pt Point
struct Pt{
LL x,y;
Pt(Ct LL &x=0,Ct LL &y=0):x(x),y(y){}
Pt operator +(Ct Pt &B)Ct{ return Pt(x + B.x , y + B.y); }
Pt operator -(Ct Pt &B)Ct{ return Pt(x - B.x , y - B.y); }
LL operator *(Ct Pt &B)Ct{ return x * B.y - y * B.x; }
}P[maxn];
int c[maxn];
bool cmp(const int &u,const int &v){ return P[u].x == P[v].x ? P[u].y > P[v].y : P[u].x < P[v].x; }
int q[maxn],R;
int main(){
//freopen("1.in","r",stdin);
for(;scanf("%d",&n) != EOF;){
rep(i,1,n) scanf("%lld%lld",&P[i].x,&P[i].y),c[i]=i;
stable_sort(c+1,c+1+n,cmp);
q[R=0] = c[1];
rep(i,2,n){
int u=c[i];
for(;R>=1 && ((P[q[R]] - P[q[R-1]]) * (P[u] - P[q[R-1]]) >= 0);)R--;
q[++R] = u;
}
int L = R;
per(i,n,1){
int u = c[i];
for(;R>L && ((P[q[R]] - P[q[R-1]]) * (P[u] - P[q[R-1]]) >= 0);)R--;
q[++R] = u;
}
LL ans = 0;
rep(i,0,R) rep(j,i+1,R) rep(k,j+1,R)
ans = max(ans , abs((P[q[j]]-P[q[i]]) * (P[q[k]]-P[q[i]])));
printf("%.2lf\n",(double)ans / 2);
}
}
垃圾题目,题意有病,建议出题人审视一下自己的conscience
A C C o d e \mathcal AC \ Code AC Code
#include
#define maxn 50005
#define LL long long
#define Ct const
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--)
using namespace std;
int n;
double sqr(double a){ return a * a; }
#define Pt Point
struct Pt{
LL x,y;
Pt(Ct LL &x=0,Ct LL &y=0):x(x),y(y){}
Pt operator +(Ct Pt &B)Ct{ return Pt(x + B.x , y + B.y); }
Pt operator -(Ct Pt &B)Ct{ return Pt(x - B.x , y - B.y); }
LL operator *(Ct Pt &B)Ct{ return x * B.y - y * B.x; }
double dist(Ct Pt &B)Ct{
return sqrt(sqr(x - B.x) + sqr(y - B.y));
}
}P[maxn];
int c[maxn];
bool cmp(const int &u,const int &v){ return P[u].x == P[v].x ? P[u].y > P[v].y : P[u].x < P[v].x; }
int q[maxn],R;
int main(){
//freopen("1.in","r",stdin);
for(;scanf("%d",&n) != EOF && n;){
rep(i,1,n) scanf("%lld%lld",&P[i].x,&P[i].y),c[i]=i;
stable_sort(c+1,c+1+n,cmp);
q[R=0] = c[1];
rep(i,2,n){
int u=c[i];
for(;R>=1 && ((P[q[R]] - P[q[R-1]]) * (P[u] - P[q[R-1]]) >= 0);)R--;
q[++R] = u;
}
int L = R;
per(i,n,1){
int u = c[i];
for(;R>L && ((P[q[R]] - P[q[R-1]]) * (P[u] - P[q[R-1]]) >= 0);)R--;
q[++R] = u;
}
double ans = 0;
rep(i,0,R-1) ans += P[q[i]].dist(P[q[i+1]]);
if(n == 2) ans /= 2;
printf("%.2lf\n",ans);
}
}
求多边形的核。
注意到Thus the edges alternate between horizontal and vertical.
所以为什么要写半平面交呢?
A C C o d e \mathcal AC \ Code AC Code
#include
#include
#define maxn 105
#define inf 0x3f3f3f3f
using namespace std;
int n,x[maxn],y[maxn],mnx,mxx,mny,mxy;
int main(){
int cas = 0;
while(~scanf("%d",&n) && n){
for(int i=0;i<n;i++) scanf("%d%d",&x[i],&y[i]);
mnx = mny = -inf;
mxx = mxy = inf;
for(int i=0;i<n;i++){
int v = (i+1)%n;
if(x[i] == x[v]){
if(y[i] > y[v]) mxx = min(mxx , x[i]);
else mnx = max(mnx , x[i]);
}
else{
if(x[i] < x[v]) mxy = min(mxy , y[i]);
else mny = max(mny , y[i]);
}
}
printf("Floor #%d\n",++cas);
if(mnx > mxx || mny > mxy) puts("Surveillance is impossible.");
else puts("Surveillance is possible.");
putchar('\n');
}
}
n n n个人,每个人有 m m m个旗子坐标为 x i , j , y i , j x_{i,j},y_{i,j} xi,j,yi,j,求在 409 5 2 4095^2 40952 的土地上每一个点 x , y x,y x,y按照 f i ( x , y ) f_i(x,y) fi(x,y)计算的最小的那个 i i i就是这个位置的主人,求每个人的土地大小。
f i ( x , y ) = m x 2 + m y 2 − 2 x ∑ j x i , j − 2 y ∑ j y i , j + ∑ j x i , j 2 + y i , j 2 f_i(x,y) = mx^2+my^2-2x\sum_{j}x_{i,j}-2y\sum_{j}y_{i,j}+\sum_{j}x_{i,j}^2+y_{i,j}^2 fi(x,y)=mx2+my2−2x∑jxi,j−2y∑jyi,j+∑jxi,j2+yi,j2
f i ( x , y ) − f k ( x , y ) = − 2 ∑ j ( x i , j − x k , j ) x − 2 ∑ j ( y i , j − y k , j ) y + ∑ j ( x i , j 2 + y i , j 2 − x k , j 2 − y k , j 2 ) ≤ 0 f_i(x,y) - f_k(x,y) = -2\sum_{j}(x_{i,j} - x_{k,j})x -2\sum_{j}(y_{i,j}-y_{k,j})y+\sum_{j}(x_{i,j}^2+y_{i,j}^2-x_{k,j}^2-y_{k,j}^2) \leq 0 fi(x,y)−fk(x,y)=−2∑j(xi,j−xk,j)x−2∑j(yi,j−yk,j)y+∑j(xi,j2+yi,j2−xk,j2−yk,j2)≤0
半平面交即可得到面积。
A C C o d e \mathcal AC \ Code AC Code
#include
#define db double
#define Ct const
#define Pt Point
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--)
#define eps 1e-8
#define maxn 205
#define maxm 2005
using namespace std;
int n,m;
db x[maxn][maxm] , y[maxn][maxm] , smx[maxn] , smy[maxn] , smx2[maxn] , smy2[maxn];
int dcmp(Ct db &a){ return a < -eps ? -1 : a > eps ? 1 : 0; }
db sqr(Ct db &a){ return a * a; }
struct Pt{
db x,y;
Pt(Ct db &x=0,Ct db &y=0):x(x),y(y){}
Pt operator +(Ct Pt &B)Ct{ return Pt(x+B.x,y+B.y); }
Pt operator -(Ct Pt &B)Ct{ return Pt(x-B.x,y-B.y); }
db operator *(Ct Pt &B)Ct{ return x * B.y - y * B.x; }
Pt operator *(Ct db &B)Ct{ return Pt(x * B , y * B); }
}qp[maxn];
struct Ln{
Pt S,T;
db ang;
Ln(Ct Pt &S=0,Ct Pt &T=0):S(S),T(T){ ang = atan2(T.y-S.y,T.x-S.x); }
bool operator <(Ct Ln &B)Ct{ return dcmp(ang - B.ang) ? ang < B.ang : (B.T - S) * (T - S) < 0; }
}L[maxn],q[maxn];
int cnt,ql,qr;
Pt Itp(Ct Pt &p1,Ct Pt &v1,Ct Pt &p2,Ct Pt &v2){ return p1 + v1 * ((p2 - p1) * v2 / (v1 * v2)); }
#define Ptln(a) a.S,a.T-a.S
db HalfPlaneInsection(){
sort(L+1,L+1+cnt);
ql=0,qr=-1;
rep(i,1,cnt) if(i == 1 || dcmp(L[i].ang - L[i-1].ang)){
for(;ql<=qr-1 && (qp[qr] - L[i].S) * (L[i].T - L[i].S) <= 0;qr--);
for(;ql<=qr-1 && (qp[ql+1] - L[i].S) * (L[i].T - L[i].S) <= 0;ql++);
q[++qr] = L[i];
if(ql<=qr-1) qp[qr] = Itp(Ptln(q[qr]),Ptln(q[qr-1]));
}
for(;ql<=qr-2 && (qp[qr] - q[ql].S) * (q[ql].T - q[ql].S) <= 0;qr--);
if(qr-ql<2) return 0;
qp[ql] = Itp(Ptln(q[qr]),Ptln(q[ql]));
db ans = 0;
rep(i,ql,qr){
int v = i + 1;
if(v > qr) v = ql;
ans += (qp[i] - qp[ql]) * (qp[v] - qp[ql]);
}
return ans / 2;
}
int main(){
int T,cas=0;
for(scanf("%d",&T);T--;){
scanf("%d%d",&n,&m);
rep(i,1,n) smx[i] = smy[i] = smx2[i] = smy2[i] = 0;
rep(i,1,n) rep(j,1,m) scanf("%lf%lf",&x[i][j],&y[i][j]) , smx[i] += x[i][j] , smx2[i] += sqr(x[i][j]) , smy[i] += y[i][j] , smy2[i] += sqr(y[i][j]);
printf("Case #%d: ",++cas);
rep(i,1,n){
cnt = 0;
rep(j,1,n) if(i^j){
db A=2 * (smx[j] - smx[i]),B=2 * (smy[j] - smy[i]),C=smx2[i] + smy2[i] - smx2[j] - smy2[j];
Pt S , T;
if(dcmp(A)) S = Pt(- C / A , 0);
else S = Pt(0 , -C / B);
T = S + Pt(B,-A);
L[++cnt] = Ln(S,T);
}
L[++cnt] = Ln(Pt(0,0) , Pt(0,4095));
L[++cnt] = Ln(Pt(0,4095) , Pt(4095,4095));
L[++cnt] = Ln(Pt(4095,4095),Pt(4095,0));
L[++cnt] = Ln(Pt(4095,0),Pt(0,0));
printf("%d%c",(int)round(HalfPlaneInsection())," \n"[i==n]);
}
}
}
在 [ 0 , 1 ] × [ 0 , 1 ] [0,1]\times [0,1] [0,1]×[0,1]的平面内每个点 ( x , y ) (x,y) (x,y)有个权重 f ( x , y ) = 2 − x − y f(x,y) = 2 - x - y f(x,y)=2−x−y,平面内有 n n n个点 { p i } \{p_i\} {pi},现在在平面上带权随机选择一个点,问离这个点最近的点是 p i p_i pi的概率。
和上题基本一样,半平面交求出每个点的范围后求积分:
假如是 S ( a , b ) , T ( c , d ) S(a,b),T(c,d) S(a,b),T(c,d),求线段 S → T S\rightarrow T S→T下的带权积分。
∫ x = a b ∫ y = 0 c + ( d − c ) ( x − a ) b − a 2 − x − y d x d y \int_{x=a}^b \int_{y=0}^{c + \frac {(d-c)(x-a)}{b-a}} 2-x-y{\rm d}x{\rm d}y ∫x=ab∫y=0c+b−a(d−c)(x−a)2−x−ydxdy
形式不太优美,设 y = k x + B y = kx + B y=kx+B
原式分成三部分:
∫ x = a b ∫ y = 0 k x + B 2 = ( b − a ) ( d + c ) \int_{x=a}^b \int_{y=0}^{kx+B} 2 = (b-a)(d+c) ∫x=ab∫y=0kx+B2=(b−a)(d+c)
∫ x = a b − x ∫ y = 0 k x + B 1 = ∫ x = a b − k x 2 − B x = k ( a 3 − b 3 ) 3 + ( a 2 − b 2 ) B 2 \int_{x=a}^b -x \int_{y=0}^{kx+B} 1=\int_{x=a}^b -kx^2-Bx = \frac {k(a^3-b^3)}3 + \frac{(a^2-b^2)B}2 ∫x=ab−x∫y=0kx+B1=∫x=ab−kx2−Bx=3k(a3−b3)+2(a2−b2)B
− ∫ x = a b ∫ y = 0 k x + B y = − ∫ x = a b k 2 x 2 + B 2 2 + k B x = k 2 ( a 3 − b 3 ) 6 + B 2 ( a − b ) 2 + k B ( a 2 − b 2 ) 2 -\int_{x=a}^b\int_{y=0}^{kx+B} y = -\int_{x=a}^b \frac {k^2x^2+B^2}2+kBx = \frac {k^2(a^3-b^3)}6+\frac {B^2(a-b)}2 + \frac {kB(a^2-b^2)}2 −∫x=ab∫y=0kx+By=−∫x=ab2k2x2+B2+kBx=6k2(a3−b3)+2B2(a−b)+2kB(a2−b2)
然后就硬算即可。
A C C o d e \mathcal AC \ Code AC Code
#include
#define db double
#define Ct const
#define Pt Point
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--)
#define eps 1e-8
#define maxn 205
#define maxm 2005
using namespace std;
int n,m;
db x[maxn],y[maxn];
int dcmp(Ct db &a){ return a < -eps ? -1 : a > eps ? 1 : 0; }
db sqr(Ct db &a){ return a * a; }
db cube(Ct db &a){ return a * a * a; }
struct Pt{
db x,y;
Pt(Ct db &x=0,Ct db &y=0):x(x),y(y){}
Pt operator +(Ct Pt &B)Ct{ return Pt(x+B.x,y+B.y); }
Pt operator -(Ct Pt &B)Ct{ return Pt(x-B.x,y-B.y); }
db operator *(Ct Pt &B)Ct{ return x * B.y - y * B.x; }
Pt operator *(Ct db &B)Ct{ return Pt(x * B , y * B); }
}qp[maxn];
struct Ln{
Pt S,T;
db ang;
Ln(Ct Pt &S=0,Ct Pt &T=0):S(S),T(T){ ang = atan2(T.y-S.y,T.x-S.x); }
bool operator <(Ct Ln &B)Ct{ return dcmp(ang - B.ang) ? ang < B.ang : (B.T - S) * (T - S) < 0; }
}L[maxn],q[maxn];
int cnt,ql,qr;
Pt Itp(Ct Pt &p1,Ct Pt &v1,Ct Pt &p2,Ct Pt &v2){ return p1 + v1 * ((p2 - p1) * v2 / (v1 * v2)); }
#define Ptln(a) a.S,a.T-a.S
db HalfPlaneInsection(){
sort(L+1,L+1+cnt);
ql=0,qr=-1;
rep(i,1,cnt) if(i == 1 || dcmp(L[i].ang - L[i-1].ang)){
for(;ql<=qr-1 && (qp[qr] - L[i].S) * (L[i].T - L[i].S) <= 0;qr--);
for(;ql<=qr-1 && (qp[ql+1] - L[i].S) * (L[i].T - L[i].S) <= 0;ql++);
q[++qr] = L[i];
if(ql<=qr-1) qp[qr] = Itp(Ptln(q[qr]),Ptln(q[qr-1]));
}
for(;ql<=qr-2 && (qp[qr] - q[ql].S) * (q[ql].T - q[ql].S) <= 0;qr--);
if(qr-ql<2) return 0;
qp[ql] = Itp(Ptln(q[qr]),Ptln(q[ql]));
db ans = 0;
rep(i,ql,qr){
int v = i + 1;
if(v > qr) v = ql;
if(dcmp(qp[i].x - qp[v].x)){
db K = (qp[v].y - qp[i].y) / (qp[v].x - qp[i].x) , B = qp[i].y - qp[i].x * K;
ans += (qp[v].x - qp[i].x) * (qp[v].y + qp[i].y)
+ K * (cube(qp[i].x) - cube(qp[v].x)) / 3
+ B * (sqr(qp[i].x) - sqr(qp[v].x)) / 2
+ sqr(K) * (cube(qp[i].x) - cube(qp[v].x)) / 6
+ sqr(B) * (qp[i].x - qp[v].x) / 2
+ K * B * (sqr(qp[i].x) - sqr(qp[v].x)) / 2;
}
}
return fabs(ans);
}
int main(){
int T,cas=0;
for(scanf("%d",&T);T--;){
scanf("%d",&n);
rep(i,1,n) scanf("%lf%lf",&x[i],&y[i]);
printf("Case #%d:\n",++cas);
rep(i,1,n){
cnt = 0;
rep(j,1,n) if(i^j){
db A=2 * (x[j] - x[i]),B=2 * (y[j] - y[i]),C=sqr(x[i]) + sqr(y[i]) - sqr(x[j]) - sqr(y[j]);
Pt S , T;
if(dcmp(A)) S = Pt(- C / A , 0);
else S = Pt(0 , -C / B);
T = S + Pt(B,-A);
L[++cnt] = Ln(S,T);
}
L[++cnt] = Ln(Pt(0,0) , Pt(0,1));
L[++cnt] = Ln(Pt(0,1) , Pt(1,1));
L[++cnt] = Ln(Pt(1,1),Pt(1,0));
L[++cnt] = Ln(Pt(1,0),Pt(0,0));
printf("%.6lf\n",HalfPlaneInsection());
}
}
}
用一堆圆来切割一个圆心为原点,半径为R的圆A,问切割完毕后圆A外围剩余部分的周长。
注意到题目中所有圆都只会和大圆 A A A相交,所以直接判断相交后加入大圆被删去的部分加回小圆加入的部分。
C o d e Code Code
#include
#define db double
#define Pi 3.1415926535897932384626433832795
using namespace std;
int m;
db R,x,y,r;
db sqr(db a){ return a * a; }
int main(){
int T;
scanf("%d",&T);
for(;T--;){
scanf("%d%lf",&m,&R);
db ans = 2 * Pi * R;
for(int i=1;i<=m;i++){
scanf("%lf%lf%lf",&x,&y,&r);
db d = sqrt(x*x+y*y);
if(d + r >= R && d - r <= R){
db a = acos((sqr(d) + sqr(R) - sqr(r)) / d / 2 / R);
db b = acos((sqr(d) + sqr(r) - sqr(R)) / d / 2 / r);
ans += b * 2 * r - a * 2 * R;
}
}
printf("%.15lf\n",ans);
}
}