JZOJ-2019-11-8 A组

T1

给定\(n\)个点的坐标(\(0 \leq xi,yi \leq 10000\))求选出任意三个点能组成的三角形的总面积。

Input

第一行\(n\)表示点数。接下来每行两个数\(x_i\),\(y_i\)表示点的坐标。

Output

一行一个浮点数保留一位小数表示面积和。

前置知识

  1. 卡常
  2. 向量

解法

众所周知\(S_{\delta}ABC = |\vec{AB} \times \vec{AC}|\)

枚举两个三角形的顶点\(A, B\), 为了避免重复我们只讨论三角形的第三个顶点在\(\vec{AB}\)右侧的情形

所求面积即为

\[\begin{align*} Ans &= \sum_{C} \vec{AB} \times \vec{AC} \\ &= \vec{AB} \times \sum_{C} \vec{AC} \end{align*} \]

维护一波前缀和即可

代码

/*code by tyqtyq*/
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define f(i,x,y) for(register int i=x, i##end=y; i<=i##end; ++i)
#define d(i,x,y) for(register int i=y, i##end=x; i>=i##end; --i)
#define FO(x) {freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);}
using namespace std;
int read(int& x){x=0; int f=1, ch=getchar(); while(!isdigit(ch)) f=ch=='-'?-1:f, ch=getchar(); while(isdigit(ch)) x=x*10+ch-'0', ch=getchar(); return x*=f;}
int read(){int x=0, f=1, ch=getchar(); while(!isdigit(ch)) f=ch=='-'?-1:f, ch=getchar(); while(isdigit(ch)) x=x*10+ch-'0', ch=getchar(); return x*f;}
int max(int x, int y){return x>y?x:y;} int min(int x, int y){return x<y?x:y;}
int n, rnk[3005];
double _[3005];
long long ans;
struct rec{
	int x, y;
}a[3005], dot[3005] ;
struct recc{
	long long x, y;
}sum;
int cmp2(rec a, rec b){
	return a.y > b.y; 
}
int cmp3(int x, int y){
	return _[x] < _[y];
}
int main(){
	//FO(triangle5);
	read(n); f(i,1,n) read(a[i].x), read(a[i].y); sort(a+1, a+1+n, cmp2);
	f(i,3,n) { 
		f(j,1,i-1) dot[j].x = a[j].x-a[i].x, dot[j].y = a[j].y-a[i].y, rnk[j]=j, _[j] = atan2(dot[j].y, dot[j].x);
		sort(rnk+1, rnk+i, cmp3) ;
		sum.x = dot[rnk[1]].x; sum.y = dot[rnk[1]].y;
		f(j,2,i-1){
			ans += sum.x*dot[rnk[j]].y - sum.y*dot[rnk[j]].x;
			sum.x += dot[rnk[j]].x; sum.y += dot[rnk[j]].y;
		}
	} 
	printf("%lld.%c\n", ans/2, "01"[ans%2]);
	return 0; //拜拜程序~ 
}

T2

表箱关有一个房间非常可怕,它由\(n\)个变异天启组成。

每个天启都会在进入房间后吐出绿弹并炸向某一个位置且范围内只有一个天启。若该位置的天启已经死亡则没有事情发生,否则该位置的天启会死亡。每个天启只能且必须吐一次绿弹(除非在它吐弹以前他就挂了)。

绿弹的飞行速度很快,在某个绿弹落地之前不会有新的绿弹被吐出。

虽然房间的天启位置和吐弹位置固定,但是吐弹顺序是随机的,所以ZCC不能很好地制定策略。

现在ZCC想知道,最少和最多有几个天启被干掉。

Input

第一行\(n\)表示天启个数。
第二行\(n\)个数\(a_i\)表示\(i\)号天启的目标是\(a_i\)
注意:行末有一个空格。

Output

一行两个数表示最少和最多有几个天启被干掉。

解法

考虑贪心最小值

循环执行:

  1. 入度为0的点\(x\)开火
  2. \(ver[x]\)被消灭
  3. \(ver[ver[x]]\)的入度减少\(1\)

若如此做最后必然只剩下一个环, 否则必有入度为\(0\)的点, 而环上答案为\(\lfloor \frac{Len+1} \rfloor\)

又因为开火次数最少, 所以贪心正确

T3

求最大的\(T \leq \frac{|S|}{2}\), 使得串\(S\)的长度为\(T\)的前后缀循环同构

解法

定有\(最长前缀={A, B}, 最长后缀={B, A}\)

枚举分支点\(i = |A|\), 记\(f(i) = |B|\), 用\(i + f(i)\)更新答案

则有\(f(i) \leq f(i+1) + 2\), 否则不符合\(A, B\)的定义

所以每次计算\(f(i)\)时, 从\(f(i+1)+2\)向下枚举第一个可行解即可

posted @ 2019-11-08 16:51  tyqtyq~!  阅读(224)  评论(0编辑  收藏  举报