IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 杭电第六场 题解 -> 正文阅读

[数据结构与算法]杭电第六场 题解

比赛传送门
作者: fn


进阶题

1001题 Yes, Prime Minister 是的,首相

题目大意
给定连续的整数序列,输出序列上包含 x x x 且区间和为质数的最短区间长度。

考察内容
数学,欧拉筛,二分查找

分析
等差数列求解区间和,可以证明,区间长度大于等于3时,只有抵消掉其余的部分留下一个或两个正整数时才能满足区间和为质数,只需要在这些情况里找出区间长度最小的方案。

x > 0 x>0 x>0 时考虑 x x x 为质数; 2 x ? 1 2x-1 2x?1 2 x + 1 2x+1 2x+1 为质数; 抵消掉其余的部分,剩下一个质数或者两个相邻正整数相加为质数。
x < 0 x<0 x<0 时则只需考虑抵消掉其余的部分,剩下一个质数或者两个相邻正整数相加为质数的情况。这种情况下通过线性筛筛出 4 e 7 4e7 4e7 的质数,二分查找留下一个或两个的方案获得答案。

#include <bits/stdc++.h>
using namespace std;
const int N = 4e7 + 5;
int vis[N], p[N], p1[N];
void init() {
    vis[0] = vis[1] = 1;
    int i, j;
    for (i = 2; i < N; i++) {
        if (!vis[i]) p[++p[0]] = i;

        for (j = 1; j <= p[0]; j++) {
            if (i * p[j] >= N) break;
            vis[i * p[j]] = 1;
            if (i % p[j] == 0) break;
        }
    }

    for (i = 1; i <= 20000001; i++) {
        if (vis[2 * i + 1] == 0) p1[++p1[0]] = i;
    }
}
bool ok(int x) { return vis[x] == 0; }
int solve(int x) {
    int ans = -1;
    if (x > 0) {
        if (x == 1) return 2;
        if (ok(x)) return 1;
        if (ok(x + x + 1)) return 2;
        if (ok(x + x - 1)) return 2;
        ans = 2 * x + 1;
        x = x + 1;
        int a1 = p[lower_bound(p + 1, p + 1 + p[0], x) - p];
        int a2 = p1[lower_bound(p1 + 1, p1 + 1 + p1[0], x) - p1];
        if (a1 <= a2)
            ans = ans + 2 * (a1 - x) + 1;
        else
            ans = ans + 2 * (a2 - x) + 2;
    } else if (x == 0)
        return 3;
    else {
        x = -x;
        ans = 2 * x + 1;
        x = x + 1;

        int a1 = p[lower_bound(p + 1, p + 1 + p[0], x) - p];
        int a2 = p1[lower_bound(p1 + 1, p1 + 1 + p1[0], x) - p1];
        if (a1 <= a2)
            ans = ans + 2 * (a1 - x) + 1;
        else
            ans = ans + 2 * (a2 - x) + 2;
    }
    return ans;
}
signed main() {
    init();
    int T, x;
    cin >> T;
    while (T--) {
        cin >> x;
        cout << solve(x) << endl;
    }
}

1005题 Median 中位数

题目大意
给定整数 1 , 2 , ? , n 1,2,?,n 12?n 。把这些数字分成 m m m 个不相交的集合,使第 j j j 个集合的中位数为 b j b_j bj? 。确定这是否可能。
注:这题中,偶数个数的集合的中位数取中间两个数中较小的那个。

分析
显然 b 1 , b 2 , ? ? ? , b m b_1, b_2, · · · , b_m b1?,b2?,???,bm? m m m 个数要放在 m m m 个不同的集合中,剩下的 n ? m n ? m n?m 个数字要放到这 m m m 个集合里且不影响每个集合的中位数。使用一个例子以方便说明:假设 n = 6 , m = 2 , b 1 = 3 , b 2 = 5 n = 6, m = 2, b_1 = 3, b_2 = 5 n=6,m=2,b1?=3,b2?=5,那么 1 , 2 , ? ? ? , n 1, 2, · · · , n 1,2,???,n 这些数会被 b b b 分成 1,2 、4、 6 这三段,且任意两段中的任意一对数字可以配对消掉。所以最后剩下的所有数字一定是同一段内的。

因此讨论两种情况:
? 如果长度最大的段的数字个数不大于其它段的数字个数之和,那么最终要么全部消掉,要么剩下一个,且剩下的这个数可以在任何一段内。如果会剩下,不妨将最后一段的数字剩下一个,此时再把最后一段的数字放到中位数最小的集合中即可满足题意,所以答案为 YES。
? 如果长度最大的段的数字个数大于其它段的数字个数之和,那么最终剩下的所有数字都在最大的这段内。设中位数小于这一段的最小值的集合的个数为 x x x,容易发现当且仅当 x x x 不小于这一段剩下的数字个数时有解。
时间复杂度 O ( n ) O(n) O(n)

官方解法:

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

int main() {
	ios::sync_with_stdio(false); cin.tie(0);
	int T;
	cin >> T;
	while (T--) {
		int n, m;
		cin >> n >> m;
		assert(m >= 1 && m <= n && n <= 100000);
		vector<int> f(n + 2);
		f[n + 1] = 1;
		while (m--) {
			int v;
			cin >> v;
			assert(v >= 1 && v <= n);
			assert(f[v] == 0);
			f[v] = 1;
		}
		vector<pair<int, int> > size;
		int have = 0;
		int count = 0;
		for (int i = 1; i <= n + 1; i++) {
			if (f[i]) {
				if (have) {
					size.push_back(make_pair(have, count));
				}
				have = 0;
				count += 1;
			}
			else {
				have += 1;
			}
		}
		sort(size.begin(), size.end());
		if (size.empty()) {
			cout << "YES\n";
			continue;
		}
		int sum = 0;
		for (auto s : size) {
			sum += s.first;
		}
		if (size.back().first <= sum - size.back().first + size.back().second) {
			cout << "YES\n";
		}
		else {
			cout << "NO\n";
		}
	}
	return 0;
}

dp:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e5+10;
int n,m,b[N],f[N],g[N];

int main(){ 
	ios::sync_with_stdio(0); cin.tie(0);
	int t; cin>>t;
	while(t--){
		cin>>n>>m;
		for(int i=1;i<=m;i++){
			cin>>b[i];
		}
		sort(b+1,b+m+1);
		
		for(int i=1;i<=m;i++) f[i]=g[i]=0;
		for(int i=1;i<=m;i++){
			f[i]=f[i-1]+b[i]-b[i-1];
			int h1=max(0,b[i]-b[i-1]-f[i-1]-1);
			g[i]=h1+max(0,g[i-1]-(b[i]-b[i-1]-1));
		}
		if(b[m]+f[m]>=n && b[m]+g[m]<=n) cout<<"YES"<<endl;
		else cout<<"NO"<<endl;
	}
}

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-08-06 10:05:03  更:2021-08-06 10:07:40 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/28 2:49:06-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计