Codeforces Div2 837(未完待续)

UPD 2022/12/12
昨天可能是晚上11.35风水不太好,刚考完概率论,该测测风水的。
赛上一共才过了3个题,补到了D,Bwa了一发之后,改了思路才过,然后A和C结果FST了

A

排个序,max一定在头和尾上
FST的原因在于 新改用的Dev C 它不提醒类型错误,然后炸两个int
相乘如果可能炸long long的话要给左边乘一个1ll,我乘到右边去了。。。。

B

这题本来觉得 通过递推求每个片段最大左端点和最小右端点,赛时交的代码

赛后发现其实段 和 段之间是有交的。。。。

比如:
3 1
1 3
这个东西显然 有两个段 【1 2】 【2 3】 然后我会把这个段内的东西给 记录重复,
然后就g了。。。。。赛时脑子瓦特了,这个想法应该还可以做下去,
但可能需要考虑的东西更多实际上是懒得写了bushi

然后换思路,每个位置的右边界显然有单调性
然后 每个位置算一遍就好了。
赛时脑子不好用这么简单还做了这么久

B的代码,我菜轻喷
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 5;
typedef long long ll;
const ll INF = 0x3f3f3f3f3f3f3f;

int main(){
	int t;
	cin >> t;
	while(t--){
		int n, m;
		cin >> n >> m;
		vector<int> R(n + 1),L(n + 1);
		for (int i = 1; i <= n; i++)R[i] = n + 1, L[i] = 0;
		for (int i = 1; i <= m; i++){
			int x, y;
			cin >> x >> y;
			if(x > y)swap(x, y);
			R[x] = min(R[x], y);
			L[y] = max(L[y], x);
		}
		ll ans = 0;
		int now = n;
		for (int i = n; i>= 1; i--){
			if(R[i]< now + 1) now = R[i] - 1;
			ans += now - i + 1;
		}
		cout << ans << "\n";
	}
}

C

赛时这个题思路很清晰,
1.如果有重复的,直接是YES
2.所有小于1×109的质因子筛出来,大约3000个
然后看一下每个数所含的这些因子里有无重复的。
3.每个数筛完这些之后,最多还剩一个大于1×109的质因子,再看一下重是否即可。

复杂度大约是N3000+logN

赛时调了许久的原因是 欧拉筛板子是从零开始往里放素数的,我给忘记了。
然后 赛时wa了一发,忘记想第三步了
FST 的原因是第一步忘记重复的是1的情况了。。。。

C
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 5;
typedef long long ll;
bool isprime[maxn];
int prime[maxn];
int used[maxn];
int get_primes(int n)
{
    memset(isprime, true ,sizeof(isprime));
	int tot = 0;
	for (int i = 2; i <= n; i++)
	{
		if (isprime[i]) prime[tot++] = i;
		for (int j = 0; prime[j] <= n / i; j++)
			//判断条件解释:我们用primes[j]筛掉合数primes[j] * i,只用筛掉小于n的合数就可以了
		{
			isprime[prime[j] * i] = 0;
			if (i % prime[j] == 0) break;
		}
	}
	return tot;
}
int main(){
	int tot = get_primes(32000);
	int t;
	cin >> t;
	
	while(t--){
		int n;
		cin >> n;
		vector<int> a(n + 1);
		map<int,int> mp;
		for (int i = 1; i <= n; i++){
			cin >> a[i];
			if(a[i] > 1)mp[a[i]]++;
			
		}
		bool ok = 0;
		for (int i = 1; i <= n; i++){
			if(mp[a[i]] > 1){
				ok = 1;
				break;
			}
		}
		if(ok){
			cout << "YES\n";
			continue;
		}
		mp.clear();
		for (int i = 1; i <= n; i++) {
			for (int j = 0; j < tot; j++){
				if(a[i] % prime[j])continue;
				while(a[i] % prime[j] == 0){
					a[i] /= prime[j];
				}
				if(used[j]){
					ok = 1;
					break;
				}
				used[j] = 1;
			}
			if(a[i] > 1)mp[a[i]]++;
			if(ok)break;
		}
		for (int i = 1; i <= n; i++){
			if(a[i] > 1 && mp[a[i]] >= 2){
				ok = 1;
				break;
			}
		}
		for (int j = 0; j < tot; j++)used[j] = 0;
		if(ok){
			cout << "YES\n";
			continue;
		}
		cout << "NO\n";
	}
}

D

D这个题属于好写不好想的DP,但我觉得还是我做的少,做多了应该不难想

  1. 跑LCA,枚举所有两个点之间的最短路径。O(N2+NLogN)

  2. 正序枚举长度

    长度为1的情况,dp[u][v] = s[u] == s[v] ? 2 : 1;

    长度大于1的情况。u1,v1分别是u相邻的u,v路径上的点 和 v相邻的u,v路径上的点。
    dp[u][v] = max(dp[u1][v], dp[u][v1]);
    dp[u][v] = max(dp[u][v],dp[u1][v1] + (s[u1] == s[v1] ? 2 : 0))

补题的时候,wa了几发,是因为vector忘记清空了。

D
#include<bits/stdc++.h>
using namespace std;
typedef pair<int, int> P;
const int maxn = 2e3 + 5;
int head[maxn], ecnt;
int dp[maxn][maxn];
int n;
int dep[maxn],f[maxn][30], dis[maxn][maxn];


struct edge {
	int v, nxt;
}e[maxn << 1];
void add_edge(int u,int v) {
	ecnt++;
	e[ecnt].nxt = head[u];
	e[ecnt].v = v;
	head[u] = ecnt;
}
void dfs(int p = 1, int fa = 0) {
	for (int i = head[p]; i != -1; i = e[i].nxt) {
		int u = e[i].v;
		if (u != fa) {
			dep[u] = dep[p] + 1;
			f[u][0] = p;
			dfs(u, p);
		}
	}
}
void init_lca() {
	for (int i = 1; i < 18; i++) {
		for (int j = 1; j <= n; j++) {
			f[j][i] = f[f[j][i - 1]][i - 1];
		}
	}
}
int lca(int a, int b) {
	if (dep[a] < dep[b])swap(a, b);
	int h = dep[a] - dep[b];
	for (int i = log2(maxn - 5); i >= 0; i--) {
		if (h >= (1 << i))
			a = f[a][i], h -= (1 << i);
	}
	if (a == b)return a;
	for (int i = log2(maxn - 5); i >= 0; i--) {
		if (f[a][i] != f[b][i])a = f[a][i], b = f[b][i];
	}
	return f[a][0];
}
int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t;
	cin >> t;
	while(t--){
		vector<P> with_dis[maxn];
		memset(head, -1, sizeof(head));
		//memset(dep, 0, sizeof dep);
		//memset(f,0,sizeof f);
		ecnt = 1;
		dep[1] = 1;
		
		cin >> n;
		string s;
		cin >> s;
		for (int i = 1; i < n; i++) {
			int a, b;
			cin >> a >> b;
			add_edge(a, b);
			add_edge(b, a);
		}
		dfs();
		init_lca();
		//memset(dis, 0, sizeof dis);
		for (int u = 1; u <= n; u++){
			dp[u][u] = 1;
			for (int v = u + 1; v <= n; v++){
				int x = lca(u, v);
				dis[u][v] = dis[v][u] = -dep[x] * 2 + dep[u] + dep[v] ;
				with_dis[dis[u][v]].push_back(make_pair(u, v));
			}
		}
		for (int len = 1; len <= n; len++){
			for (auto now : with_dis[len]){
				int u = now.first, v = now.second;
				if(len == 1){
					if(s[u - 1] == s[v - 1])dp[u][v] = dp[v][u] = 2;
					else dp[u][v] = dp[v][u]= 1;
				}
				else {
					int u1 = -1, v1 = -1;
					for (int i = head[u]; i != -1; i = e[i].nxt){
						if(dis[e[i].v][v] < dis[u][v]){
							u1 = e[i].v;
							break;
						}
					}
				
					for (int i = head[v]; i != -1; i = e[i].nxt) {
						if(dis[u][e[i].v] < dis[u][v]){
							v1 = e[i].v;
							break;
						}
					}
					
					dp[u][v] = dp[v][u] = dp[u1][v1] + (s[u - 1] == s[v - 1] ? 2 : 0);
					//if(u == 3 && v == 5) cout << s[u - 1] << s[v - 1] << u1 << v1<< endl;
					dp[u][v] = dp[v][u] = max(dp[u1][v], dp[u][v]);
					dp[u][v] = dp[v][u] = max(dp[u][v1], dp[u][v]);
				}
			}
			
		}
		
		int ans = 0;
		for (int i = 1; i <= n; i++){
			for (int j = 1; j <= n; j++){
				//cout << dp[i][j] << endl;
				ans = max(dp[i][j], ans);
			}
		}
		cout << ans << endl;
	}
}

posted @   浪释归衣  阅读(29)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App
点击右上角即可分享
微信分享提示