首页 > 其他分享 >暑假专题训练 计算几何与字符串 2023-7-20

暑假专题训练 计算几何与字符串 2023-7-20

时间:2023-07-22 16:56:58浏览次数:49  
标签:typedef PDD 20 int ans 暑假 2023 sens include

未补完

B. Queue


概要:找出每一个人(坐标为i)从ni + 1的第一个比他年纪小的人,坐标为j,他的不愉悦值为j - i - 1。注意有相同大小要靠右取,并且最年轻的人若与当前这个人年纪相同则答案为-1

算法:二分。

做法:tag数组来记录从n1的最小年纪。对每一个人(坐标i),从i + 1n二分查找出最接近这个人年龄且比这个人年龄要小且最靠近右边的人的坐标,求他们之间的人数即为答案。

code
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <queue>
#include <stack>
#include <deque>
#include <cmath>
#include <string>
#include <set>
using namespace std;

typedef long long LL;
typedef pair<int, int> PII;
int dx[4] = { -1, 1, 0, 0 }, dy[4] = { 0, 0, -1, 1 };

const int N = 100010;

int n;
map<int, int> mp;
int w[N], ans[N], tag[N];

int sr(int x, int l, int r)
{
	while (l < r)
	{
		int mid = (l + r + 1) >> 1;
		if (tag[mid] < x)l = mid;
		else r = mid - 1;
	}
	return l;
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);

	cin >> n;
	for (int i = 1; i <= n; i++)cin >> w[i];

	for (int i = n; i >= 1; i--)
	{
		if (i + 1 <= n)
		{
			if (w[i] > tag[i + 1])
			{
				int p = sr(w[i], i + 1, n);
				ans[i] = p - i - 1;
				tag[i] = tag[i + 1];
			}
			else if (w[i] == tag[i + 1])ans[i] = -1, tag[i] = tag[i + 1];
			else ans[i] = -1, tag[i] = w[i];
		}
		else ans[i] = -1, tag[i] = w[i];
	}

	for (int i = 1; i <= n; i++)printf("%d ", ans[i]);

	return 0;
}

 

C. Repetitive Elements


概要:给定一个字符串,找出这个串中相同且最长的不重合的子串。

算法:二分。

做法:对于这个字符串我们二分的串的长度为[1, s.size() / 2]。这是因为大的两个符合题意的串必定包含小的两个符合题意的串。然后注意边界问题就可以了。

code
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <queue>
#include <stack>
#include <deque>
#include <cmath>
#include <string>
#include <set>
using namespace std;

typedef long long LL;
typedef pair<int, int> PII;
int dx[4] = { -1, 1, 0, 0 }, dy[4] = { 0, 0, -1, 1 };

const int N = 100010;

int len, ans;
string s;

bool check(int ln)
{
	for (int i = 0; i <= (int)s.size() - 2 * ln; i++)
	{
		for (int j = i + ln; j <= s.size() - ln; j++)
		{
			if (s.substr(i, ln) == s.substr(j, ln))
			{
				if (ln > len)len = ln, ans = i;
				return true;
			}
		}
	}

	return false;
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);

	int t;
	cin >> t;
	while (t--)
	{
		len = -1e9, ans = -1;
		cin >> s;

		int l = 1, r = (int)s.size() / 2;
		while (l < r)
		{
			int mid = (l + r + 1) >> 1;
			if (check(mid))l = mid;
			else r = mid - 1;
		}

		for (int i = ans; i < ans + len; i++)cout << s[i];
		cout << endl;
	}

	return 0;
}

 

E.Nearest vectors


概要:找出两个向量的夹角最小。

算法:排序、数学

做法:对于每一个坐标我们用atan2(x, y)算出其从弧度。对每一个向量的弧度按照从小到大来排序。依次遍历每一个向量,我们总是用下一个向量的弧度减去我们当前遍历的向量的弧度,即为两者最小夹角。最后特别处理一下最后一个向量和第一个向量的夹角,再排个序就可以得到最小夹角。

code
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <queue>
#include <stack>
#include <deque>
#include <cmath>
#include <string>
#include <set>
#define double long double
using namespace std;

typedef long long LL;
typedef pair<int, int> PII;
typedef pair<double, int> PDI;
typedef pair<double, double> PDD;
int dx[4] = { -1, 1, 0, 0 }, dy[4] = { 0, 0, -1, 1 };

const int N = 100010;
const double eps = 1e-200;

int n;
PDI tangle[N];
PII w[N];

struct Node
{
	int a, b;
    double du;
}node[N];

bool cmp1(PDI x, PDI y)
{
	return x.first < y.first;
}

bool cmp2(Node x, Node y)
{
	return x.du < y.du;
}

double get_tangle(double y, double x)
{
	return atan2(y, x);
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);

	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		cin >> w[i].first >> w[i].second;
		tangle[i].first = get_tangle(w[i].second, w[i].first), tangle[i].second = i;
	}

	sort(tangle + 1, tangle + n + 1, cmp1);

	for (int i = 1; i <= n; i++)
	{ 
		if (i + 1 <= n)
		{
			node[i] = { tangle[i].second, tangle[i + 1].second,  tangle[i + 1].first - tangle[i].first};
		}
		else
		{
			node[i] = { tangle[i].second, tangle[1].second, 2 * acos(-1) - (tangle[i].first - tangle[1].first) };
		}
	}

	sort(node + 1, node + n + 1, cmp2);

	printf("%d %d", node[1].a, node[1].b);

	return 0;
}

 

F. Are You Safe?


做法:在给出的c个点中找出凸包,判断p个点是否在凸包中。注意排序的点一定要从最左边开始按逆时针构成一个环。

算法:Andrew、判断点是否在凸包中(用凸包的各条边的向量和各条边的起始点到判断点的向量的叉乘来判断)

code
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <queue>
#include <stack>
#include <deque>
#include <cmath>
#include <string>
#include <set>
#define fir first
#define sec second
using namespace std;

typedef long long LL;
typedef pair<int, int> PII;
typedef pair<double, int> PDI;
typedef pair<double, double> PDD;
int dx[4] = { -1, 1, 0, 0 }, dy[4] = { 0, 0, -1, 1 };

const int N = 200010;
double eps = 1e-8;

PDD get_vec(PDD a, PDD b)
{
	return { b.fir - a.fir, b.sec - a.sec };
}

double cross(PDD a, PDD b)
{
	return a.fir * b.sec - a.sec * b.fir;
}

bool check(PDD a, PDD b, PDD c)
{
	PDD ab = get_vec(a, b), bc = get_vec(b, c);
	double res = cross(ab, bc);
	if (fabs(res) < eps || res > 0)return true;
	else return false;
}

vector<PDD> andrew(vector<PDD>& sens)
{
	sort(sens.begin(), sens.end());

	vector<PDD> ans;
	vector<int> I{ 0 }, st(sens.size());
	for (int i = 1; i < sens.size(); i++)
	{
		while (I.size() > 1 && check(sens[I[(int)I.size() - 2]], sens[(int)I.back()], sens[i]))
			st[(int)I.back()] = 0, I.pop_back();
		st[i] = 1, I.push_back(i);
	}

	for (int i = sens.size() - 2; i >= 0; i--)
	{
		if (st[i])continue;
		while (I.size() > 1 && check(sens[I[(int)I.size() - 2]], sens[(int)I.back()], sens[i]))
			st[(int)I.back()] = 0, I.pop_back();
		st[i] = 1, I.push_back(i);
	}


	for (int i = 0; i < I.size() - 1; i++)ans.push_back(sens[I[i]]);
	return ans;
}

void solve(int ca)
{
	int c, p;
	vector<PDD> sensors;
	vector<PDD> points;
	cin >> c >> p;
	for (int i = 0; i < c; i++)
	{
		PDD t;
		cin >> t.fir >> t.sec;
		sensors.push_back(t);
	}

	cout << "Case " << ca << endl;
	auto plg = andrew(sensors);
	reverse(plg.begin() + 1, plg.end());
	for (int i = 0; i < plg.size(); i++)cout << plg[i].fir << ' ' << plg[i].sec << endl;
	cout << plg[0].fir << ' ' << plg[0].sec << endl;
	
	for (int i = 0; i < p; i++)
	{
		PDD t;
		cin >> t.fir >> t.sec;
		bool flag = true;
		for (int j = 0; j < plg.size(); j++)
		{
			PDD ab, ac;
			if (j < plg.size() - 1)ab = get_vec(plg[j], plg[j + 1]), ac = get_vec(plg[j], t);
			else ab = get_vec(plg[j], plg[0]), ac = get_vec(plg[j], t);
			double res = cross(ab, ac);
			if (fabs(res) < eps || res > 0)continue;
			else
			{
				flag = false;
				break;
			}
		}
		if (flag)cout << t.fir << ' ' << t.sec << ' ' << "is unsafe!" << endl;
		else cout << t.fir << ' ' << t.sec << ' ' << "is safe!" << endl;
	}
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);

	int t, ca = 0;
	cin >> t;
	while (t--)
	{
		solve(++ca);
		cout << endl;
	}

	return 0;
}

标签:typedef,PDD,20,int,ans,暑假,2023,sens,include
From: https://www.cnblogs.com/dkdklcx/p/17566905.html

相关文章

  • 黑魂 209武器开关控制
    把状态机的hit修改,选中hit到ground的箭头点开settings,将interruptionSource改成CurrentState。   点击状态机attack1ha,把里面的动画改成同名,点击edit改名,点开event,把攻击动画帧和收刀动画帧设置两个点(WeaponEnable和WeaponDisable)。最后点Apply a,b,c三个动作都是这......
  • Au2021中文版Audition2021免激活下载 新功能介绍
    AdobeAuditionCS6是一款功能强大的音频编辑器,更是一个专业音频编辑和混合环境。为了方便大家下载使用,winwin7给大家带来的这款AU音频编辑器去除了其他国家的语言,让软件体积变得更小,运行更快,使用更流畅...完善的工具集,其中包含用于创建、混合、编辑和复原音频内容的多轨、波形和光......
  • 「刷题记录」[JSOI2007] 文本生成器
    第一道AC自动机+DP题。题目链接:P4052[JSOI2007]文本生成器-洛谷|计算机科学教育新生态(luogu.com.cn)利用容斥原理的思想,答案就是所有串的数量减去不可读的串的数量。设\(dp\left(i,j\right)\)表示串长为\(i\),在AC自动机上走到编号为\(j\)时不经过单词结......
  • 2023.7.22-假期周进度报告
    本周(7.16-7.22)主要学习大数据相关的最基本知识。下周准备进行休息。周日,进行VMware的下载和虚拟机镜像的下载和安装,完成了VMware的下载和安装,虚拟机的下载和安装,VMnet8虚拟网卡的基本配置,虚拟机主机名和ip地址的配置,遇到了虚拟机镜像下载慢的问题,解决方法是从所看课程中给的资料......
  • 2023/7/22(2)宽搜练习马走日
     #include<bits/stdc++.h>usingnamespacestd;intqwq[12][2]={{1,2},{1,-2},{-1,2},{-1,-2},{-2,-1},{-2,1},{2,1},{2,-1},{2,2},{-2,-2},{2,-2},{-2,2}};intax,ay,bx,by;boolmp[105][105];structnode{intx,y,step;node(){}node(constint......
  • 2023牛客多校7.21补题
    D-TheGameofEating题意:一共有m道菜,n个人轮流点一道菜,一共点k道。第i个人对第j道菜的喜爱程度\(A_{i,j}\)对所有人公开,一个人点了菜所有人都可以吃到。每个人都希望最大化自己的喜爱程度之和,求最终的点菜集合。分析:很容易想到每个人点菜时都点当前剩下的菜中自己最喜爱的,但是......
  • P2567 [SCOI2010] 幸运数字
    题目链接题目中询问数据范围达到了1e10,且要求找符合要求数的个数,很容易让我想到数位dp,但其实每必要,发现幸运数字只有\(2^{10}\)个,答案就是近似幸运数+幸运数-两者交集,考虑容斥,每个\([l,r]\)之间的可能被之前的幸运数更新多次,通过容斥,很容易知道1个幸运数个数-2个幸运数lcm个......
  • 快乐暑假第四周
    本周完成了对于hadoop的基本配置:可以打开页面: 同时完成了hadoop的使用命令1.1文件路径增删改查系列:hdfsdfs-mkdirdir创建文件夹hdfsdfs-rmrdir删除文件夹dirhdfsdfs-ls查看目录文件信息hdfsdfs-lsr递归查看文件目录信息hdfsdfs-statpath返回指定路径......
  • P1060 [NOIP2006 普及组] 开心的金明 题解
    思路01背包模版题,唯一不同的是加了一个条件就是价格与重要度的乘积。转移方程为:dp[j]=max(dp[j],dp[j-w[i]]+w[i]*v[i]);这里加了滚动数组优化。代码#include<bits/stdc++.h>#definelllonglong#defineldlongdoubleusingnamespacestd;inlinevoidread(int&x){......
  • 牛客暑假多校 2023 第二场
    写在前面比赛地址:https://ac.nowcoder.com/acm/contest/57356。我是MINUS-FIFTEEN级超级战犯。澄清一下,我不是声优厨,我不是声优厨,我不是声优厨。同样是题目选补,我是飞舞。以下个人向难度排序。I签到。随便手玩一下就行。D虽然每个人都倾向于吃到自己最喜欢的菜,但给在......