首页 > 其他分享 >[赛记] 暑假集训CSP提高模拟20 21

[赛记] 暑假集训CSP提高模拟20 21

时间:2024-08-15 19:05:20浏览次数:13  
标签:赛记 20 21 int long ans include 500005 dis

Kanon 40pts

签到题,但是不会,所以打了暴力;

正解时考虑相邻两个雪球,只有两种情况:它们的覆盖区间有交集或无交集,那么如果我们找出了无交集的最后一天,我们就很容易判断剩下的一堆雪该被谁拿走,于是我们二分找出这一天即可;赛时确实想不到二分

时间复杂度:$ \Theta(n \log n) $;

点击查看代码
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int n, q;
long long a[500005];
long long w[500005];
long long sum[500005];
long long an[500005];
long long ma[500005], mi[500005];
namespace BIT{
	long long tr[2][5000005];
	inline int lowbit(int x) {
		return x & (-x);
	}
	void add(int pos, long long d) {
		for (int i = pos; i <= q; i += lowbit(i)) {
			tr[0][i] = max(tr[0][i], d);
			tr[1][i] = min(tr[1][i], d);
		}
	}
	long long ask(int s, int pos) {
		if (s == 0) {
			long long ans = -0x3f3f3f3f3f3f3f3f;
			for (int i = pos; i; i -= lowbit(i)) {
				ans = max(ans, tr[0][i]);
			}
			return ans;
		} else {
			long long ans = 0x3f3f3f3f3f3f3f3f;
			for (int i = pos; i; i -= lowbit(i)) {
				ans = min(ans, tr[1][i]);
			}
			return ans;
		}
	}
}
using namespace BIT;
bool ck(int x, long long s) {
	long long mma = ma[x];
	long long mmi = mi[x];
	if (mmi > 0) return mma <= s;
	else return mma - mmi <= s;
}
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> q;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
	}
	for (int i = 1; i <= q; i++) {
		cin >> w[i];
	}
	for (int i = 1; i <= n; i++) {
		tr[0][i] = -0x3f3f3f3f3f3f3f3f;
		tr[1][i] = 0x3f3f3f3f3f3f3f3f;
	}
	long long mma = 0;
	long long mmi = 0;
	for (int i = 1; i <= q; i++) {
		sum[i] = sum[i - 1] + w[i];
		mma = max(mma, sum[i]);
		mmi = min(mmi, sum[i]);
		add(i, sum[i]);
		ma[i] = max(0ll, ask(0, i));
		mi[i] = min(0ll, ask(1, i));
	}
	an[1] += (-mmi);
	an[n] += mma;
	for (int i = 1; i <= n - 1; i++) {
		int l = 1;
		int r = q;
		int ans = 0;
		while(l <= r) {
			int mid = (l + r) >> 1;
			if (ck(mid, a[i + 1] - a[i])) {
				l = mid + 1;
				ans = mid;
			} else {
				r = mid - 1;
			}
		}
		mma = ma[ans];
		mmi = mi[ans];
		ans++;
		an[i + 1] += (-mmi);
		an[i] += mma;
		if (ans > q) continue;
		if (w[ans] < 0) {
			an[i + 1] -= (-mmi);
			an[i + 1] += (a[i + 1] - a[i] - mma);
		} else {
			an[i] -= mma;
			an[i] += (a[i + 1] - a[i] + mmi);
		}
	}
	for (int i = 1; i <= n; i++) {
		cout << an[i] << '\n';
	}
	return 0;
}

黎明与萤火 0pts

签到题爆零。。。

赛时打的是正解,但没有判掉已经确定的答案导致错误;

考虑从下往上找(因为从上往下可能会使原来根节点和数个子节点都是偶数,结果删了根节点后数个子节点都是奇数导致不能再选,而从下往上可以反过来甚至避免这个问题,总的来说就是尽量选一个点,使其影响的点较少),那么我们可以采用类似拓扑排序的思路,开一个优先队列,重载运算符使其将深度大的且是偶数的点放在上面,每次取出队头是判断一下现在的奇偶以及被计算进答案的情况,然后将其符合条件且未被计算进答案的点放进去,完事以后判断一下即可;

时间复杂度:每个点至多会进队其度数次(这也是正确性的保证),但是总的遍历次数是度数次的,乘上优先队列的复杂度,那么总的时间复杂度为 $ \Theta(n \log n) $;

点击查看代码
#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
using namespace std;
int n;
vector<int> v[500005];
vector<int> ans;
int d[500005], dep[500005], dd[500005];
bool vis[500005];
struct sss{
	int x;
	bool operator <(const sss &A) const {
		return dep[x] < dep[A.x];
	}
	bool operator >(const sss &A) const {
		return dep[x] < dep[A.x];
	}
};
priority_queue<sss> q; 
void dfs(int x, int fa) {
	dep[x] = dep[fa] + 1;
	for (int i = 0; i < v[x].size(); i++) {
		int u = v[x][i];
		if (u == fa) continue;
		dfs(u, x);
	}
}
bool solve() {
	while(!q.empty()) {
		while(!q.empty() && (d[q.top().x] % 2 != 0 || vis[q.top().x])) q.pop();
		if (q.empty()) break;
		sss tt = q.top();
		q.pop();
		int t = tt.x;
		vis[t] = true;
		d[t] = 0;
		ans.push_back(t);
		for (int i = 0; i < v[t].size(); i++) {
			int u = v[t][i];
			if (vis[u]) continue;
			d[u]--;
			if (d[u] % 2 == 0) {
				q.push(sss{u});
			}
		}
	}
	for (int i = 1; i <= n; i++) {
		if (!vis[i]) return false;
	}
	return true;
}
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n;
	int x;
	for (int i = 1; i <= n; i++) {
		cin >> x;
		if (x == 0) continue;
		v[i].push_back(x);
		v[x].push_back(i);
		d[x]++;
		d[i]++;
	}
	dfs(1, 0);
	for (int i = 1; i <= n; i++) {
		if (d[i] % 2 == 0) {
			q.push(sss{i});
		}
	}
	if (solve()) {
		cout << "YES" << '\n';
		for (int i = 0; i < ans.size(); i++) {
			cout << ans[i] << '\n';
		}
	} else {
		cout << "NO";
	}
	return 0;
}

Darling Dance 10pts

赛时没看这道题,输出了个0就走了,拿了10pts

这个题把最短路DAG建出来就行,然后从1开始对其BFS(DFS也行),选k条边即可;

对于最短路DAG,只需在最短路成功更新时记录一下从哪里更新的即可(即其前驱节点);

注意k=0的情况;

点击查看代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
using namespace std;
int n, m, k;
struct sss{
	int t, ne, w;
}e[2000005];
int h[2000005], cnt;
void add(int u, int v, int ww) {
	e[++cnt].t = v;
	e[cnt].ne = h[u];
	h[u] = cnt;
	e[cnt].w = ww;
}
int dis[500005];
bool vis[500005];
int fr[500005], id[500005];
vector<int> v[500005];
int w(int x, int y) {
	if (x % y == 0) return x / y;
	else return x / y + 1;
}
void dij(int x) {
	memset(dis, 0x3f, sizeof(dis));
	memset(vis, 0, sizeof(vis));
	dis[x] = 0;
	priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > q;
	q.push({0, x});
	while(!q.empty()) {
		int xu = q.top().second;
		q.pop();
		if (vis[xu]) continue;
		vis[xu] = true;
		for (int i = h[xu]; i; i = e[i].ne) {
			int u = e[i].t;
			if (dis[u] > dis[xu] + e[i].w) {
				dis[u] = dis[xu] + e[i].w;
				fr[u] = xu;
				id[u] = w(i, 2);
				q.push({dis[u], u});
			}
		}
	}
}
queue<int> p;
int ans[500005], o;
void bfs() {
	p.push(1);
	while(!p.empty()) {
		int t = p.front();
		p.pop();
		for (int i = 0; i < v[t].size(); i++) {
			int u = v[t][i];
			if (o == k) return;
			p.push(u);
			ans[++o] = id[u];
		}
	}
}
int main() {
	cin >> n >> m >> k;
	int x, y, w;
	for (int i = 1; i <= m; i++) {
		cin >> x >> y >> w;
		add(x, y, w);
		add(y, x, w);
	}
	dij(1);
	for (int i = 1; i <= n; i++) {
		v[fr[i]].push_back(i);
	}
	bfs();
	cout << o << '\n';
	for (int i = 1; i <= o; i++) {
		cout << ans[i] << ' ';
	}
	return 0;
}

最近比赛打的真是越来越CD了。。。

标签:赛记,20,21,int,long,ans,include,500005,dis
From: https://www.cnblogs.com/PeppaEvenPig/p/18361533

相关文章

  • CSP21
    总结:两个题的checker我都自己写了一个,MD,耽误太多时间了,\(Linux\)的\(checker\)使用要加g++checker.cpp-o程序名这题,性质题,首先发现一个树\(n-1\)条边,每次删偶数条边,所以\(n\)必须是奇数,其次我们发现优先删去深度深的点较为优,删完后,我们发现还剩下一些散点散树,再\(dfs\)一......
  • 洛谷——P1093 [NOIP2007 普及组] 奖学金
    题目背景NOIP2007普及组T1题目描述某小学最近得到了一笔赞助,打算拿出其中一部分为学习成绩优秀的前555名学生发奖学金。期末,每个学生都有......
  • 蓝桥杯2016 C/C++程序设计 B组
    抽签//X星球要派出一个5人组成的观察团前往W星。//其中://A国最多可以派出4人。//B国最多可以派出2人。//C国最多可以派出2人。//....//那么最终派往W星的观察团会有多少种国别的不同组合呢?//下面的程序解决了这个问题。//数组a[]中既是每个国家可以派出的最多的名......
  • 『模拟赛』暑假集训CSP提高模拟21
    『模拟赛』暑假集训CSP提高模拟21终于没RE了!不枉我辛辛苦苦调了几个小时...(但是暴力没打完...(逃T1黎明与萤火DFS序乱糊+贪心注意要先消除叶子结点。Elaina'sCodeintn,fa[N],rdeg[N],hd[N],idx,ans[N],cnt;boolvis[N];stack<int>sta;structEDGE{ intnxt,to;}......
  • 王者荣耀2024曹操最强吸血出装
    在《王者荣耀》中曹操是一名战士类型的英雄,具备位移、控制和输出的能力,他在团战中可以前排抗伤,甚至可以扮演坦克或刺客的角色,为了最大化曹操的伤害输出,选择合适的装备非常重要,本篇文章将介绍2024年曹操最强的六神装出装顺序推荐和铭文推荐!在王者荣耀中,出装顺序是很重要的,我......
  • 【2-sat】P5782 [POI2001] 和平委员会
    P5782[POI2001]和平委员会大意:n个集合每个集合有两个点i,i+1一共2n个点每个集合选一个点到另一个空集S里面有m个约束条件i和j不能在一起求可行的集合S思路:2-sat对ij而言建图(i,j邻居)和(j,i的邻居),邻居就是他们所属的集合的另一个点然后判断同同一个集......
  • XMind 2024安装教程(Pro版)
    下载链接:https://docs.qq.com/doc/DSWZBQUtkeU1QS2N0软件介绍Xmind是一款全功能的思维导图和头脑风暴软件。像大脑的瑞士军刀一般,助你理清思路,捕捉创意。精良的设计,流畅的体验,强大的功能,多年精细打磨,为你提供极致的产品体验。全功能:提供9种专业的的思维导图结构,丰富的模......
  • EndNote21.4安装教程(最新版)
    下载链接:https://docs.qq.com/doc/DSVZXTVRvYXdEd21q软件介绍、EndNote文献管理软件是由科睿唯安公司开发的文献管理软件,可用于帮助研究人员管理和组织参考文献、引用和注释,从文献检索、组织科研活动、撰写论文,到发表文章和共享科研成果,助力机构用户加速科研流程。EndNote......
  • 2024-08-15 财富负面信念的破开迷思
    2024-08-15  上了自由蓝图课,从里面拷贝出来的。盘点一下自己的负面信念,              我自己可以觉知到的总共命中了18条,分别是1,2,3,4,6:7,8,9,10,13,15,18,22,26,27,28,29,30。其他的可能也有,但是没有觉知到。破除信念的一个简单方法就是问一......
  • 【2-sat】P4171 [JSOI2010] 满汉全席
    P4171[JSOI2010]满汉全席-洛谷大意:n个点m个条件形如m1,h32,满足n个条件思路:2-sat让m=0,h=1,然后转换为imjh的建图,注意傻逼题目的数字可能是多位数不能直接x[1]-'0'#include<cstdio>#include<stack>#include<iostream>#include<cstring>#include<cma......