11/8训练笔记

P6273[eJOI2017] 魔法 题解

考虑定义\(S_{r_k} = \Sigma_{i = 1}^{r}[s_i = k]\),那么对于任意一个子串\([l,r]\),其为有魔法的子串的充要条件为\(S_{c_{r}} - S_{c_{l - 1}}\)对于任意的,在\(s\)中出现了的\(c\)为定值。

任取一个在\(s\)中出现了的字符\(A\),那么上述充要条件可转换为\(S_{c_{r}} - S_{c_{l - 1}} = S_{A_{r}} - S_{A_{l - 1}}\)对于\(s\)中出现的每个字符\(c\)都成立。

移项,得\(S_{c_{r}} - S_{A_{r}} = S_{c_{l - 1}} - S_{A_{l - 1}}\)

拿一个vector<int>维护\({S_{c_{r}} - S_{A_{r}}|c \in S}\)即可

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

代码:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<set>
#include<map>
using namespace std;
int cnt1[100010],cnt[266],n,k,now,ans;
string s;
map<vector<int>,int> mp;
vector<int> v;
char a1[100010];
int main()
{
	cin >> n >> s;
	s = s;
	strcpy(a1,s.c_str());
	sort(a1,a1 + n);
	mp[v = (vector<int>(k = unique(a1,a1 + n) - a1,0))] = 1;
	for(int i = 0;i < n;i++) {
		if(s[i] != a1[0]) {
			v[lower_bound(a1,a1 + k,s[i]) - a1]++;
		} else {
			for(auto &j:v) {
				j--;
			}
			v[0]++;
		}
		((ans += mp[v]++) %= (int)(1e9 + 7));
	}
	cout << ans << "\n";
}

P8579[CoE R5/Stoi2029] 半岛铁盒 题解

考虑最坏情况

即一个点是正无穷,剩下的都是0

然后每次分出来的气压肯定能少则少

随后注意到\(x\)显然可以二分。

那么考虑check函数怎么写

注意到BFS即可,但是需要注意的是每次BFS可能会T

对于每个源点只进行一次BFS,BFS出dep数组,在check时进行DP即可。

代码:

#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#define int long long
using namespace std;
int dep[100010],vis[100010],n,m,p,q,u,v;
vector<int> E[100010];
queue<int> q1;
double d[100010],ans;
void Bfs(int now) {
	for(int i = 1;i <= n;i++) {
		dep[i] = 0;
		vis[i] = 0;
	}
	q1.push(now);
	dep[now] = 1;
	vis[now] = 1;
	while(!q1.empty()) {
		int x = q1.front();
		q1.pop();
		for(auto i:E[x]) {
			if(vis[i]) continue;
			vis[i] = true;
			dep[i] = dep[x] + 1;
			q1.push(i);
		}
	}
}
bool check(double mid) {
	double sum = 1.0 * (q - p) / q;
	d[0] = 0;
	d[1] = 1.0 * p / q;
	for(int i = 1;i <= n;i++) {
		if(!dep[i] || (dep[i] == 1)) continue;
		d[dep[i]] = d[dep[i] - 1] / mid;
		sum -= d[dep[i]];
	}
	return (sum >= 0.0);
}
signed main()
{
	cin >> n >> m >> p >> q;
	for(int i = 1;i <= m;i++) {
		cin >> u >> v;
		E[u].push_back(v);
		E[v].push_back(u);
	}
	for(int i = 1;i <= n;i++) {
		Bfs(i);
		sort(dep + 1,dep + n + 1);
		int cnt = 60;
		double l = 1 - 0.00000001,r = 3e9 + 0.00000001;
		while(cnt--) {
			double mid = (l + r) / 2;
			if(check(mid)) {
				r = mid;
			} else {
				l = mid;
			}
		}
		ans = max(ans,r);
	}
	printf("%.7lf",ans);
}
posted @ 2023-11-08 18:55  IANYEYZ  阅读(9)  评论(0编辑  收藏  举报