基础练习1

基础练习1

HDU1214 圆桌会议

题意:

有一个\(1 \sim n\)的升序圆排列,我们每次能让相邻两个数交换位置,至少操作多少次,能使得每个数前后两个数都发生交换。

解题思路:

其实就是将一个\(1 \sim n\)的圆排列通过交换相邻元素得到\(n \sim 1\)的圆排列。

简单手玩一下,不难发现,我们总能将一个圆排列分成两部分\(1 \sim\lfloor \frac{n}{2} \rfloor ,n - \lfloor \frac{n}{2} \rfloor \sim n\)

因为每个数总要我们将每个部分看作一个长度为\(len\)数列,那么通过交换相邻两项是的数列完全逆序需要\(\frac{len \times (len - 1)}{2}\)次操作。两部分同理。

代码:

#include<bits/stdc++.h>
using namespace std;
using ll = long long;


void solve()
{
	int n;
	while(cin >> n)
	{
		if(n < 3)
		{
			cout << 0 << endl;
		}
		else
		{
			ll a = n / 2;
			ll b = n - a;
			ll ans = (a * (a - 1)) / 2 + (b * (b - 1)) / 2;
			cout << ans << endl;
		}
	}
}

int main()
{
	int t = 1;
	while(t --)
	{
		solve();
	}
	return 0;
}

HDU1870 愚人节的礼物

题意:

圆括号一层套一层,字符串中一个字符B,找到B所在的层数。

解题思路:

找到左括号加一,找到右括号减一,找到B结束,答案为之前累计的数。

代码:

#include<bits/stdc++.h>
using namespace std;
using ll = long long;


void solve()
{
	string s;
	while(cin >> s)
	{
		int ans = 0;
		for(auto c : s)
		{
			if(c == '(')
			{
				ans ++;
			}
			else if(c == ')')
			{
				ans --;
			}
			else
			{
				cout << ans << endl;
				break;
			}
		}
	}
}

int main()
{
	int t = 1;
	while(t --)
	{
		solve();
	}
	return 0;
}

HDU2203 亲和串

题意:

给定字符串A,B。其中A可看做首位相接的循环字符,判断B是否是A的一个子串。

解题思路:

在A的后面加一个A。然后字符串哈希。由于B的长度固定了,所以可直接遍历\(O(1)\)判断。

代码:

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
const int P = 131;
using ll = long long;
using ull = unsigned long long;
typedef unsigned long long ull;
ull p[N];
ull h1[N];
ull h2[N];

ull get(int l,int r)
{
	return h1[r] - h1[l-1] * p[r - l + 1];
}

void solve()
{
	string s1,s2;
	while(cin >> s1 >> s2)
	{
		
		if(s2.size() > s1.size())
		{
			puts("no");
			continue;
		}
		s1 += s1;
		s1 = ' ' + s1;
		s2 = ' ' + s2;
		p[0] = 1;
		ll n = s1.size();
		for(int i = 1;i<n;i ++)
		{
			h1[i] = h1[i-1] * P + s1[i];
			p[i] = p[i - 1] * P;
//			cout << i << ' ' << endl;
		}
//		cout << endl;
		for(int i = 1;i<s2.size();i++)
		{
			h2[i] = h2[i-1] * P + s2[i];
		}
		ll len = s2.size() - 1;
		bool f = false;
		for(int i = 1;i<=s1.size() - len;i++)
		{
			if(get(i,i + len - 1) == h2[len])
			{
//				cout << get(i,i + len - 1) << ' ' << h2[len] << endl;
//				cout << i << endl;
				f = true;
				break;
			}
		}
		if(f)
		{
			puts("yes");
		}
		else
		{
			puts("no");
		}
	}
}

int main()
{
	int t = 1;
	while(t --)
	{
		solve();
	}
	return 0;
}

天真愚蠢的麻瓜

题意:

给定4个二维坐标,前三个在一个圆内或者圆上,该圆尽量小。判断第4个坐标是否也在圆内。

解题思路:

覆盖三个点的最小圆,这里可枚举7中情况:

  • 三点共圆 +1
  • 分别以三个点为圆心 +3
  • 分别以三个点连成的三条边的中点为圆心 + 3

枚举即可。

代码:

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
const int P = 131;
using ll = long long;
using ull = unsigned long long;
typedef unsigned long long ull;
using pdd = pair<double,double>;
#define fi first
#define se second
int T = 0;

pdd tpc(double x1, double y1, double x2, double y2, double x3, double y3)
{
	double a = 2 * (x2 - x1);
	double b = 2 * (y2 - y1);
	double c = x2 * x2 - x1 * x1 + y2 * y2 - y1 * y1;
	double d = 2 * (x3 - x1);
	double e = 2 * (y3 - y1);
	double f = x3 * x3 - x1 * x1 + y3 * y3 - y1 * y1;
	double g = a * e - b * d;
	return {(c * e - b * f) / g,(a * f - d * c) / g};
}

double get(double x1,double y1,double x2,double y2)
{
	return sqrtl((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}

pdd mid(double x1,double y1,double x2,double y2)
{
	double x = (x1 + x2) / 2;
	double y = (y1 + y2) / 2;
	return {x,y};
}

void solve()
{
	vector<pdd> v(3);
	cin >> v[0].fi >> v[0].se >> v[1].fi >> v[1].se >> v[2].fi >> v[2].se;
	v.push_back(mid(v[0].fi,v[0].se,v[1].fi,v[1].se));
	v.push_back(mid(v[0].fi,v[0].se,v[2].fi,v[2].se));
	v.push_back(mid(v[2].fi,v[2].se,v[1].fi,v[1].se));
	v.push_back(tpc(v[0].fi,v[0].se,v[1].fi,v[1].se,v[2].fi,v[2].se));
	double a,b;
	cin >> a >> b;
	double mind  = 1e9 + 1;
	double ans = 0;
	vector<double> r;
	vector<double> dist;
	vector<bool> st(v.size());
	for(int i = 0;i < v.size();i++)
	{ 
		if(i == 0)
		{
			double d1 = get(v[i].fi,v[i].se,v[1].fi,v[1].se);
			double d2 = get(v[i].fi,v[i].se,v[2].fi,v[2].se);
			double tr = max(d1,d2);
			double td = get(v[i].fi,v[i].se,a,b);
			r.push_back(tr);
			dist.push_back(td);
			st[i] = true;
		}
		else if(i == 1)
		{
			double d1 = get(v[i].fi,v[i].se,v[0].fi,v[0].se);
			double d2 = get(v[i].fi,v[i].se,v[2].fi,v[2].se);
			double tr = max(d1,d2);
			double td = get(v[i].fi,v[i].se,a,b);
			r.push_back(tr);
			dist.push_back(td);
			st[i] = true;
		}
		else if(i == 2)
		{
			double d1 = get(v[i].fi,v[i].se,v[1].fi,v[1].se);
			double d2 = get(v[i].fi,v[i].se,v[0].fi,v[0].se);
			double tr = max(d1,d2);
			double td = get(v[i].fi,v[i].se,a,b);
			r.push_back(tr);
			dist.push_back(td);
			st[i] = true;
		}
		else if(i == 3)
		{
			double d1 = get(v[i].fi,v[i].se,v[1].fi,v[1].se);
			double d2 = get(v[i].fi,v[i].se,v[2].fi,v[2].se);
			if(d2 > d1)
			{
				st[i] = false;
			}
			double tr = max(d1,d2);
			double td = get(v[i].fi,v[i].se,a,b);
			r.push_back(tr);
			dist.push_back(td);
			st[i] = true;
		}
		else if(i == 4)
		{
			double d1 = get(v[i].fi,v[i].se,v[1].fi,v[1].se);
			double d2 = get(v[i].fi,v[i].se,v[2].fi,v[2].se);
			if(d1 > d2)
			{
				st[i] = false;
			}
			double tr = max(d1,d2);
			double td = get(v[i].fi,v[i].se,a,b);
			r.push_back(tr);
			dist.push_back(td);
			st[i] = true;
		}
		else if(i == 5)
		{
			double d1 = get(v[i].fi,v[i].se,v[0].fi,v[0].se);
			double d2 = get(v[i].fi,v[i].se,v[2].fi,v[2].se);
			if(d1 > d2)
			{
				st[i] = false;
			}
			double tr = max(d1,d2);
			double td = get(v[i].fi,v[i].se,a,b);
			r.push_back(tr);
			dist.push_back(td);
			st[i] = true;
		}
		else
		{
//			cout <<"nisdfsadsafdasfasdf" <<endl;
			double d1 = get(v[i].fi,v[i].se,v[1].fi,v[1].se);
			double d2 = get(v[i].fi,v[i].se,v[2].fi,v[2].se);
			double tr = max(d1,d2);
			double td = get(v[i].fi,v[i].se,a,b);
//			cout << td << endl;
			r.push_back(tr);
			dist.push_back(td);
			st[i] = true;
		}
		mind = min(mind,r.back());
	}
//	cout << mind <<endl;
	for(int i = 0;i<v.size();i++)
	{
//		cout << i << ' ';
//		cout << v[i].fi << ' ' << v[i].se;
//		cout << ' ' << r[i] << ' ' << dist[i] << endl;
		if(mind == r[i] && st[i])
		{
			if(dist[i] > r[i])
			{
				printf("Case #%d: Safe\n",T);
				return;
			}
		}
	}
	printf("Case #%d: Danger\n",T);
}

int main()
{
	int t = 1;
	cin >> t;
	while(t --)
	{
		T ++;
		solve();
	}
	return 0;
}

HDU1285 确定比赛名次

题意:

给定n个队伍,m个二元关系,(a,b)指的是a排在b的前面。输出从前到后的排序,确保给定关系的同时小的编号在前。

解题思路:

a向b连有向边,按拓扑序就是前后关系。

要求先标编号小的,那就用优先队列记录度数为0的点。

代码:

#include<bits/stdc++.h>
using namespace std;
const int N = 1e4 + 10;
const int P = 131;
using ll = long long;
using ull = unsigned long long;
typedef unsigned long long ull;
using pdd = pair<double,double>;
#define fi first
#define se second

void solve()
{
	int n,m;
	while(cin >> n >> m)
	{
		
		vector<int> e[n + 1];
		vector<int> d(n + 1,0);
		for(int i = 1;i<=m;i++)
		{
			int a,b;
			cin >> a >> b;
			e[a].push_back(b);
			d[b] ++;
		}
		priority_queue<int,vector<int>,greater<int>> q;
		for(int i = 1;i<=n;i++)
		{
			if(!d[i])
			{
				q.push(i);
			}
		}
		vector<int> ans;
		while(q.size())
		{
			auto u = q.top();
			q.pop();
			ans.push_back(u);
			for(auto v : e[u])
			{
				d[v] --;
				if(d[v] == 0)
				{
					q.push(v);
				}
			}
		}
		for(int i = 0;i < ans.size();i++)
		{
			cout << ans[i];
			if(i != ans.size() - 1)
			{
				cout << ' ';
			}
			else
			{
				cout << endl;
			}
		}
	}
	
}

int main()
{
	int t = 1;
	while(t --)
	{
		solve();
	}
	return 0;
}

HDU1540 Tunnel Warfare

题意:

开始有个\(1 \sim n\)共n个点的直线连通块。我们根据指令进行操作:

D x: x处成断点

Q x: x所在直线连通块有多少个点

R:恢复上一个变成断点的位置

解题思路:

用栈记录断点。

对于查找,我们只要找当前点\(v\)的前面一个断点和该断点的后面一个断点就可以了。两相邻断点间的点个数就是连通块中点的个数。当然,如果自己是断点,那么返回的就是\(0\)了。

对于记录断点和查找断点我们用\(set\)\(log\)插入,\(log\)查找。

时间复杂度\(O(mlogn)\)

代码:

#include<bits/stdc++.h>
using namespace std;
const int N = 1e4 + 10;
const int P = 131;
using ll = long long;
using ull = unsigned long long;
typedef unsigned long long ull;
using pdd = pair<double,double>;
#define fi first
#define se second

void solve()
{
	int n,m;
	while(cin >> n >> m)
	{
		stack<int> q;
		set<int> s;
		s.insert(0);
		s.insert(n + 1);
		while(m --)
		{
			string t;
			cin >> t;
			if(t == "D")
			{
				int x;
				cin >> x;
				s.insert(x);
				q.push(x);
			}
			else if(t == "R")
			{
				auto u = q.top();
				q.pop();
				s.erase(u);
			}
			else
			{
				int u;
				cin >> u;
				if(s.find(u) != s.end())
				{
					cout << 0 << endl;
				}
				else
				{
					auto l = s.upper_bound(u);
					auto r = l --;
	//				cout << (*r) << endl;
	//				cout << (*l) << endl;
					cout << ((*r) - (*l) - 1) << endl;
				}
			}
		}
	}
	
}

int main()
{
	int t = 1;
	while(t --)
	{
		solve();
	}
	return 0;
}
posted @ 2023-11-17 03:10  value0  阅读(12)  评论(0)    收藏  举报