2016-2017 ACM-ICPC, South Pacific Regional Contest (SPPC 16)

题目链接  Codeforces_Gym_101177

Problem A  Anticlockwise Motion

直接模拟即可

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<string>
#include<vector>
#include<map>
#include<set>
#include<queue>
using namespace std;
int a,b;
pair<int,int> p1,p2;
pair<int,int> calc(int x)
{
	pair<int,int> ans;
	int y=sqrt(x*1.0);
	if ((y&1)&&(y*y==x))
	{
		ans.first=ans.second=(-(y-1)>>1);
		return ans;
	}
	if ((y&1)==0) y--;
	int p=y*y;
	ans.first=ans.second=(-(y-1)>>1);
	if (x-p<=(y+1))
	{
		ans.second--;
		ans.first+=(x-p)-1;
		return ans;
	}
	p+=(y+1);
	ans.first+=y;
	ans.second--;
	if (x-p<=y+1)
	{
		ans.second+=(x-p);
		return ans;
	}
	ans.second+=(y+1);
	p+=(y+1);
	if (x-p<=y+1)
	{
		ans.first-=(x-p);
		return ans;
	}
	ans.first-=(y+1);
	p+=y+1;
	ans.second-=(x-p);
	return ans;
}
int main()
{
	scanf("%d%d",&a,&b);
	p1=calc(a);
	p2=calc(b);

	printf("%d
",abs(p1.first-p2.first)+abs(p1.second-p2.second));
	return 0;
}

Problem D Dendroctonus

非正解

任意选取三个点确定一个圆然后判断。

但是这样有特殊情况……如果两个点和另一个很远的点构成一个很大的圆,

这个圆可能恰好符合题意。

所以我们再加入8个坐标足够大的点再枚举判断就可以了。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<string>
#include<vector>
#include<map>
#include<set>
#include<queue>
using namespace std;
#define y1 khjk
#define y2 kjkj
struct point
{
	double x,y;
	point(){}
	point(double _x,double _y):x(_x),y(_y)
	{}
	point operator -(const point &b) const
	{
		return point(x-b.x,y-b.y);
	}
	double operator *(const point &b) const
	{
		return x*b.x+y*b.y;
	}
	double operator ^(const point &b) const
	{
		return x*b.y-y*b.x;
	}
};
struct line
{
	point s,e;
	double a,b,c;
	line()
	{

	}
	line (point _s,point _e):s(_s),e(_e)
	{
		a=e.y-s.y;
		b=s.x-e.x;
		c=e.x*s.y-s.x*e.y;
	}
};
double xmult(point p0,point p1,point p2)
{
	return (p1-p0)^(p2-p0);
}
const double eps = 1e-1;
double sgn(double x)
{
	if(fabs(x) < eps)return 0;
	if(x < 0)return -1;
	else return 1;
}
bool inter(line l1,line l2)
{
	return
		max(l1.s.x,l1.e.x) >= min(l2.s.x,l2.e.x) &&
		max(l2.s.x,l2.e.x) >= min(l1.s.x,l1.e.x) &&
		max(l1.s.y,l1.e.y) >= min(l2.s.y,l2.e.y) &&
		max(l2.s.y,l2.e.y) >= min(l1.s.y,l1.e.y) &&
		sgn((l2.s-l1.s)^(l1.e-l1.s))*sgn((l2.e-l1.s)^(l1.e-l1.s)) <= 0 &&
		sgn((l1.s-l2.s)^(l2.e-l2.s))*sgn((l1.e-l2.s)^(l2.e-l2.s)) <= 0;
}
bool samepoint(point p1,point p2)
{
	if (fabs(p1.x-p2.x)>eps) return false;
	if (fabs(p1.y-p2.y)>eps) return false;
	return true;
}
double cross(point sp,point ep,point op)
{
	return (sp.x-op.x)*(ep.y-op.y)-(sp.y-op.y)*(ep.x-op.x);
}
double area(point p1,point p2,point p3)
{
	return fabs(cross(p1,p2,p3))/2;
}
point intersection(line u,line v)
{
	point p;
	p.x=(cross(v.e,u.e,u.s)*v.s.x-cross(v.s,u.e,u.s)*v.e.x)/(cross(v.e,u.e,u.s)-cross(v.s,u.e,u.s));
	p.y=(cross(v.e,u.e,u.s)*v.s.y-cross(v.s,u.e,u.s)*v.e.y)/(cross(v.e,u.e,u.s)-cross(v.s,u.e,u.s));
	return p;
}
point interpoint(line l1, line l2)
{
	point tmp;
	if(fabs(l1.b)<eps)
	{
		tmp.x=-l1.c/l1.a;
		tmp.y=(-l2.c-l2.a*tmp.x)/l2.b;
	}
	else
	{
		tmp.x=(l1.c*l2.b-l1.b*l2.c)/(l1.b*l2.a-l2.b*l1.a);
		tmp.y=(-l1.c-l1.a*tmp.x)/l1.b;
	}
	return tmp;
}
double findx(double y,line l)
{
	return (-l.c-l.b*y)/l.a;
}
double findy(double x,line l)
{
	if (fabs(l.b)<eps)
		return -1e250;
	return (-l.c-l.a*x)/l.b;
}
point tcircle(point pt1, point pt2, point pt3, double &radius)
{
	double x1 = pt1.x, x2 = pt2.x, x3 = pt3.x;
	double y1 = pt1.y, y2 = pt2.y, y3 = pt3.y;
	double a = x1 - x2;
	double b = y1 - y2;
	double c = x1 - x3;
	double d = y1 - y3;
	double e = ((x1 * x1 - x2 * x2) + (y1 * y1 - y2 * y2)) / 2.0;
	double f = ((x1 * x1 - x3 * x3) + (y1 * y1 - y3 * y3)) / 2.0;
	double det = b * c - a * d;
	if( fabs(det) <eps)
	{
		radius = -1;
		return point(0,0);
	}

	double x0 = -(d * e - b * f) / det;
	double y0 = -(a * f - c * e) / det;
	radius = hypot(x1 - x0, y1 - y0);
	return point(x0, y0);
}
int n,cnt1=0,cnt2=0;
point p1[1100],p2[1100];
double dis(point p1,point p2)
{
	return sqrt((p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y));
}
void calc(point P,point Q)
{
	double r=dis(P,Q)/2;
	point p;
	p.x=(P.x+Q.x)/2;
	p.y=(P.y+Q.y)/2;
	bool can=true;
	int l;
	for (l=1;l<=cnt1;l++)
		if ((p1[l].x-p.x)*(p1[l].x-p.x)+(p1[l].y-p.y)*(p1[l].y-p.y)-r*r>eps)
		{
			can=false;
			break;
		}
	if (!can) return;
	for (l=1;l<=cnt2;l++)
		if (r*r-(p2[l].x-p.x)*(p2[l].x-p.x)-(p2[l].y-p.y)*(p2[l].y-p.y)>eps)
		{
			can=false;
			break;
		}
	if (can)
	{
		puts("No");
		exit(0);
	}

}
bool onSegment(point Pi , point Pj , point Q)
{
	if((Q.x - Pi.x) * (Pj.y - Pi.y) == (Pj.x - Pi.x) * (Q.y - Pi.y)
			&& min(Pi.x , Pj.x) <= Q.x && Q.x <= max(Pi.x , Pj.x)
			&& min(Pi.y , Pj.y) <= Q.y && Q.y <= max(Pi.y , Pj.y))
		return true;
	else
		return false;
}
int main()
{
	scanf("%d",&n);
	int i,j,k,l;
	for (i=1;i<=n;i++)
	{
		point p;
		scanf("%lf%lf",&p.x,&p.y);
		char c[3];
		scanf("%s",c);
		if (c[0]=='I')
			p1[++cnt1]=p;
		else p2[++cnt2]=p;
	}
	if (cnt1<=1)
	{
		puts("No");
		return 0;
	}
	else if (cnt1==2)
	{
		calc(p1[1],p1[2]);
		bool can=true;
		for (i=1;i<=cnt2;i++)
			if (onSegment(p1[1],p1[2],p2[i]))
			{
				can=false;
				break;
			}
		if (can)
			puts("No");
		else puts("Yes");
		return 0;
	}
	int cnt3=cnt1;

	cnt3++;
	p1[cnt3].x=10000;
	p1[cnt3].y=10000;
	cnt3++;
	p1[cnt3].x=-10000;
	p1[cnt3].y=10000;
	cnt3++;
	p1[cnt3].x=10000;
	p1[cnt3].y=-10000;
	cnt3++;
	p1[cnt3].x=-10000;
	p1[cnt3].y=-10000;
	cnt3++;
	p1[cnt3].x=0;
	p1[cnt3].y=-10000;
	cnt3++;
	p1[cnt3].x=0;
	p1[cnt3].y=10000;
	cnt3++;
	p1[cnt3].x=10000;
	p1[cnt3].y=0;
	cnt3++;
	p1[cnt3].x=-10000;
	p1[cnt3].y=-0;

	for (i=1;i<=cnt3-2;i++)
		for (j=i+1;j<=cnt3-1;j++)
			for (k=j+1;k<=cnt3;k++)
			{
				double r;
				point p=tcircle(p1[i],p1[j],p1[k],r);
				if (r==-1)
				{
					calc(p1[i],p1[j]);
					calc(p1[i],p1[k]);
					calc(p1[j],p1[k]);
					continue;
				}
				if (r!=-1)
				{
					bool can=true;
					for (l=1;l<=cnt1;l++)
						if ((p1[l].x-p.x)*(p1[l].x-p.x)+(p1[l].y-p.y)*(p1[l].y-p.y)-r*r>eps)
						{
							can=false;
							break;
						}
					if (!can) continue;
					for (l=1;l<=cnt2;l++)
						if (r*r-(p2[l].x-p.x)*(p2[l].x-p.x)-(p2[l].y-p.y)*(p2[l].y-p.y)>eps)
						{
							can=false;
							break;
						}
					if (can)
					{
						puts("No");
						return 0;
					}
				}

			}
	puts("Yes");
	return 0;
}

Problem E

Problem F

其实这题就是预处理+判断

总状态数不超过3^9个

对于题目中所给的4张表,我们搞出所有的状态

然后暴力判断即可。

#include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b)	for (int i(a); i <= (b); ++i)
#define	dec(i, a, b)	for (int i(a); i >= (b); --i)	

typedef long long LL;

const int N = 2e4 + 10;
const char* ch = " FUT";

int an[6][6], oo[6][6], im[6][6], eq[6][6];
int mul[6][6];
int f[N][4][4];
int cnt;
int c[6][6];
int ct;
int T;

set <int> mp;

void init(){
	int s = 1;
	rep(i, 1, 3){
		rep(j, 1, 3){
			mul[i][j] = s;
			s *= 10;
		}
	}
}

inline int get(int cnt){
	int ret = 0;
	rep(i, 1, 3) rep(j, 1, 3) ret += f[cnt][i][j] * mul[i][j];
	return ret;
}

inline void work(int cnt){
	int h = get(cnt);
	mp.insert(h);
}

inline void output(int cnt){
	dec(i, 3, 1) dec(j, 3, 1) printf("%d", f[cnt][i][j]); putchar(10);
}

inline void out(){
	dec(i, 3, 1) dec(j, 3, 1) printf("%d", c[i][j]); putchar(10);
}

inline void check(){
	int ret = 0;
	rep(i, 1, 3) rep(j, 1, 3) ret += c[i][j] * mul[i][j];
	if (mp.count(ret)) return;
//	out();
	mp.insert(ret);
	++cnt;
	rep(i, 1, 3) rep(j, 1, 3) f[cnt][i][j] = c[i][j];
}

void judge(){
	int ret = 0;
	rep(i, 1, 3) rep(j, 1, 3) ret += c[i][j] * mul[i][j];
	if (mp.count(ret)) puts("definable");
	else puts("undefinable");

}

int main(){

	freopen("1.txt", "r", stdin);
	freopen("2.txt", "w", stdout);

	init();
	rep(i, 1, 3) rep(j, 1, 3){
		an[i][j] = min(i, j);
		oo[i][j] = max(i, j);
		eq[i][j] = (i == j) ? 3 : 1;
	}

	im[1][1] = im[1][2] = im[1][3] = 3;
	im[2][1] = 2; im[2][2] = im[2][3] = 3;
	im[3][1] = 1; im[3][2] = 2; im[3][3] = 3;

	++cnt; rep(i, 1, 3) rep(j, 1, 3) f[cnt][i][j] = im[i][j];  work(cnt);
	++cnt; rep(i, 1, 3) rep(j, 1, 3) f[cnt][i][j] = an[i][j];  work(cnt);
	++cnt; rep(i, 1, 3) rep(j, 1, 3) f[cnt][i][j] = oo[i][j];  work(cnt);
	++cnt; rep(i, 1, 3) rep(j, 1, 3) f[cnt][i][j] = eq[i][j];  work(cnt);

	rep(op, 1, 10){
		ct = cnt;
		rep(k, 1, ct){
			rep(l, 1, 4){
				rep(i, 1, 3) rep(j, 1, 3) c[i][j] = f[k][i][j];
				rep(i, 1, 3) rep(j, 1, 3){
					c[i][j] = f[l][f[k][i][j]][i];
					check();
					c[i][j] = f[l][f[k][i][j]][j];
					check();
					rep(i, 1, 3) rep(j, 1, 3) c[i][j] = f[k][i][j];
				}
			}
		}
	//	printf("%d
", cnt);
	}
	
//	printf("%d
", cnt);

	scanf("%d", &T);
	while (T--){
		rep(i, 1, 3){
			rep(j, 1, 3){
				char ch[2];
				scanf("%s", ch);
				if (ch[0] == 'F') c[i][j] = 1;
				if (ch[0] == 'U') c[i][j] = 2;
				if (ch[0] == 'T') c[i][j] = 3;
			}
		}


		judge();
	}
	return 0;
}

Problem G

Problem H

Problem I  Intuidiff II

这题目描述真是绕得可以

其实题意就是按给出的顺序选出若干个不相交并且左端点递增的区间。

区间的价值是这个区间的长度+1

然后就变成水题了。

#include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b)	for (int i(a); i <= (b); ++i)
#define dec(i, a, b)	for (int i(a); i >= (b); --i)
#define MP		make_pair
#define fi		first
#define se		second


typedef long long LL;

const int N = 2e5 + 10;

struct node{
	int x, y;
	LL val;
	friend bool operator < (const node &a, const node &b){
		return a.x < b.x;
	}
}  d[N];

int a[N], b[N];
int n;
int cnt = 0;
int tt;

LL c[N];
LL f[N];

void update(int x, LL val){
	for (; x <= N - 2; x += x & -x) c[x] = max(c[x], val);
}

LL query(int x){
	LL ret = 0;
	for (; x; x -= x & -x) ret = max(ret, c[x]);
	return ret;
}


int main(){

	scanf("%d", &n);
	rep(i, 1, n * 2) scanf("%d", a + i), b[i] = a[i];
	rep(i, 1, n) d[i].val = 0ll + a[i * 2] - a[i * 2 - 1] + 1;
	sort(b + 1, b + 2 * n + 1);
	cnt = unique(b + 1, b + 2 * n + 1) - b - 1;
	rep(i, 1, n * 2) a[i] = lower_bound(b + 1, b + cnt + 1, a[i]) - b;

	rep(i, 1, n){
		++tt;
		d[i].x = a[tt];
		++tt;
		d[i].y = a[tt];
	}

	rep(i, 1, n){
		f[i] = query(d[i].x - 1) + d[i].val;
		update(d[i].y, f[i]);
	}

	LL ans = 0;
	rep(i, 1, N - 2) ans = max(ans, f[i]);
	printf("%lld
", ans);
	return 0;
}
原文地址:https://www.cnblogs.com/cxhscst2/p/7635858.html