首页 > 其他分享 >[赛记] csp-s加赛1

[赛记] csp-s加赛1

时间:2024-09-18 11:47:33浏览次数:1  
标签:赛记 int tr mid long id ask 加赛 csp

小W与制胡串谜题 50pts

这种题,就是想到 + 玄学;

感觉刚接触OI时做过这种题,当时学得少,蒙一下就过了。现在蒙不了了,也确实可供想的方向很多,所以像这种签到题比较不好做;

字符串数组是可以 $ sort $ 的,所以我们重载 $ cmp $ 为 a + b < b + a 即可;

至于正确性,直观感觉一下确实是对的,要严谨证明一下的话需要证一下偏序关系。

点击查看代码
#include <iostream>
#include <cstdio>
#include <string>
#include <algorithm>
using namespace std;
int n;
string s[300005];
bool cmp(string a, string b) {
	return a + b < b + a;
}
int main() {
	freopen("a.in", "r", stdin);
	freopen("a.out", "w", stdout);
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> s[i];
	}
	sort(s + 1, s + 1 + n, cmp);
	for (int i = 1; i <= n; i++) {
		cout << s[i];
	}
	return 0;
}

小W与伙伴招募 85pts

这题数据比较NB,赛时我打的假贪心拿了85pts,但暴力能拿95pts(貌似和正解得分没啥区别)。。。

很显然的一个思路是贪心,每次顺序优先购买花费最少的钻石;

这样我们就得到了一个 $ \Theta(nm) $ 的暴力;

考虑优化,我们发现,每次操作相当于一个区间乘2(在原数组基础上)和单点减的问题,所以我们把每个点看成一个类似于 $ xb_i + b $ 的形式,然后开两个线段树维护一下 $ x $ 和 $ b $ 即可;

由于每次操作需要在线段树上二分,所以时间复杂度是 $ \Theta(n \log^2 m) $ 的 (貌似可以 $ \Theta(n \log m) $ 实现)

点击查看代码
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
#define int long long
int n, m;
long long c[500005];
long long sum[500005], suma[500005];
int len, pos;
long long ans;
struct sss{
	long long a, b;
	bool operator <(const sss &A) const {
		if (a != A.a) return a < A.a;
		else return b < A.b;
	}
}e[500005];
int cnt;
inline int ls(int x) {
	return x << 1;
}
inline int rs(int x) {
	return x << 1 | 1;
}
namespace xseg{
	struct sss{
		int l, r;
		long long sum, lz, val;
		bool z;
	}tr[2000005];
	inline void push_down(int id) {
		if (tr[id].z) {
			tr[ls(id)].z = tr[rs(id)].z = true;
			tr[ls(id)].sum = tr[rs(id)].sum = tr[ls(id)].val = tr[rs(id)].val = 0;
			tr[ls(id)].lz = tr[rs(id)].lz = -1;
			tr[id].z = false;
		}
		if (tr[id].lz != -1) {
			tr[ls(id)].lz += ((tr[ls(id)].lz == -1) ? (tr[id].lz + 1) : tr[id].lz);
			tr[rs(id)].lz += ((tr[rs(id)].lz == -1) ? (tr[id].lz + 1) : tr[id].lz);
			tr[ls(id)].sum += tr[id].lz * (sum[tr[ls(id)].r] - sum[tr[ls(id)].l - 1]);
			tr[rs(id)].sum += tr[id].lz * (sum[tr[rs(id)].r] - sum[tr[rs(id)].l - 1]);
			tr[ls(id)].val += tr[id].lz * (suma[tr[ls(id)].r] - suma[tr[ls(id)].l - 1]);
			tr[rs(id)].val += tr[id].lz * (suma[tr[rs(id)].r] - suma[tr[rs(id)].l - 1]);
			tr[id].lz = -1;
		}
	}
	inline void push_up(int id) {
		tr[id].sum = tr[ls(id)].sum + tr[rs(id)].sum;
		tr[id].val = tr[ls(id)].val + tr[rs(id)].val;
	}
	void bt(int id, int l, int r) {
		tr[id].l = l;
		tr[id].r = r;
		tr[id].lz = -1;
		tr[id].z = false;
		if (l == r) return;
		int mid = (l + r) >> 1;
		bt(ls(id), l, mid);
		bt(rs(id), mid + 1, r);
	}
	void add(int id, int l, int r, long long d) {
		if (tr[id].l >= l && tr[id].r <= r) {
			if (d == 0) {
				tr[id].lz = -1;
				tr[id].sum = 0;
				tr[id].val = 0;
				tr[id].z = true;
				return;
			}
			tr[id].sum += (sum[tr[id].r] - sum[tr[id].l - 1]) * d;
			tr[id].val += (suma[tr[id].r] - suma[tr[id].l - 1]) * d;
			tr[id].lz += ((tr[id].lz == -1) ? (d + 1) : d);
			return;
		}
		push_down(id);
		int mid = (tr[id].l + tr[id].r) >> 1;
		if (l <= mid) add(ls(id), l, r, d);
		if (r > mid) add(rs(id), l, r, d);
		push_up(id);
	}
	long long ask_sum(int id, int l, int r) {
		if (tr[id].l >= l && tr[id].r <= r) return tr[id].sum;
		push_down(id);
		int mid = (tr[id].l + tr[id].r) >> 1;
		if (r <= mid) return ask_sum(ls(id), l, r);
		else if (l > mid) return ask_sum(rs(id), l, r);
		else return ask_sum(ls(id), l, mid) + ask_sum(rs(id), mid + 1, r);
	}
	long long ask_val(int id, int l, int r) {
		if (tr[id].l >= l && tr[id].r <= r) return tr[id].val;
		push_down(id);
		int mid = (tr[id].l + tr[id].r) >> 1;
		if (r <= mid) return ask_val(ls(id), l, r);
		else if (l > mid) return ask_val(rs(id), l, r);
		else return ask_val(ls(id), l, mid) + ask_val(rs(id), mid + 1, r);
	}
}
namespace bseg{
	struct sss{
		int l, r;
		long long sum, val, lz;
	}tr[2000005];
	void bt(int id, int l, int r) {
		tr[id].l = l;
		tr[id].r = r;
		tr[id].lz = -1;
		if (l == r) return;
		int mid = (l + r) >> 1;
		bt(ls(id), l, mid);
		bt(rs(id), mid + 1, r);
	}
	inline void push_up(int id) {
		tr[id].sum = tr[ls(id)].sum + tr[rs(id)].sum;
		tr[id].val = tr[ls(id)].val + tr[rs(id)].val;
	}
	inline void push_down(int id) {
		if (tr[id].lz == 0) {
			tr[ls(id)].lz = tr[rs(id)].lz = tr[ls(id)].sum = tr[rs(id)].sum = tr[ls(id)].val = tr[rs(id)].val = 0;
			tr[id].lz = -1;
			return;
		}
	}
	void add(int id, int l, int r, long long d, bool is) {
		if (tr[id].l >= l && tr[id].r <= r) {
			if (is) {
				tr[id].sum += d;
				tr[id].val += d * e[l].a;
				return;
			}
			tr[id].lz = 0;
			tr[id].sum = 0;
			tr[id].val = 0;
			return;
		}
		push_down(id);
		int mid = (tr[id].l + tr[id].r) >> 1;
		if (l <= mid) add(ls(id), l, r, d, is);
		if (r > mid) add(rs(id), l, r, d, is);
		push_up(id);
	}
	long long ask_sum(int id, int l, int r) {
		if (tr[id].l >= l && tr[id].r <= r) return tr[id].sum;
		push_down(id);
		int mid = (tr[id].l + tr[id].r) >> 1;
		if (r <= mid) return ask_sum(ls(id), l, r);
		else if (l > mid) return ask_sum(rs(id), l, r);
		else return ask_sum(ls(id), l, mid) + ask_sum(rs(id), mid + 1, r);
	}
	long long ask_val(int id, int l, int r) {
		if (tr[id].l >= l && tr[id].r <= r) return tr[id].val;
		push_down(id);
		int mid = (tr[id].l + tr[id].r) >> 1;
		if (r <= mid) return ask_val(ls(id), l, r);
		else if (l > mid) return ask_val(rs(id), l, r);
		else return ask_val(ls(id), l, mid) + ask_val(rs(id), mid + 1, r);
	}
}
bool ck(int x, long long o) {
	long long s = xseg::ask_sum(1, 1, x) + bseg::ask_sum(1, 1, x);
	if (s > o) return true;
	else return false;
}
main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		cin >> c[i];
	}
	long long a, b;
	for (int i = 1; i <= m; i++) {
		cin >> a >> b;
		if (b != 0) {
			e[++cnt].a = a;
			e[cnt].b = b;
		}
	}
	sort(e + 1, e + 1 + cnt);
	for (int i = 1; i <= cnt; i++) {
		if (e[i].b == -1) {
			pos = i;
			break;
		}
		sum[i] = sum[i - 1] + e[i].b;
		suma[i] = suma[i - 1] + e[i].a * e[i].b;
	}
	if (pos != 1) xseg::bt(1, 1, pos - 1);
	if (pos != 1) bseg::bt(1, 1, pos - 1);
	for (int i = 1; i <= n; i++) {
		if (pos != 1) xseg::add(1, 1, pos - 1, 1);
		int l = 1;
		int r = pos - 1;
		int now = pos;
		if (pos != 1) {
			while(l <= r) {
				int mid = (l + r) >> 1;
				if (ck(mid, c[i])) {
					now = mid;
					r = mid - 1;
				} else {
					l = mid + 1;
				}
			}
		}
		long long s = 0;
		now--;
		if (now >= 1) {
			s = xseg::ask_sum(1, 1, now) + bseg::ask_sum(1, 1, now);
			ans += xseg::ask_val(1, 1, now) + bseg::ask_val(1, 1, now);
			xseg::add(1, 1, now, 0);
			bseg::add(1, 1, now, 0, 0);
		}
		if (s == c[i]) continue;
		c[i] -= s;
		now++;
		if (now == pos) {
			ans += e[pos].a * c[i];
			continue;
		}
		ans += e[now].a * c[i];
		bseg::add(1, now, now, -c[i], 1);
	}
	cout << ans;
	return 0;
}

标签:赛记,int,tr,mid,long,id,ask,加赛,csp
From: https://www.cnblogs.com/PeppaEvenPig/p/18418173

相关文章

  • CSP-J/S复赛提交指南!防止爆零必读!
    文件提交模版代码:#include<bits/stdc++.h>usingnamespacestd;intmain(){//打开输入文件,输出文件freopen("test.in","r",stdin);freopen("test.out","w",stdout);//正常的逻辑代码//关闭输入文件输出文件fclose(stdin);......
  • CSP初赛知识点:Linux 系统
    CSP初赛知识点:Linux系统前言近年CSP初赛几乎前5道选择题都有一两道有关Linux系统的使用,所以作为备战CSP-J/S2024的资料,整理下来啦。祝各位今年所有考试都能考出自己满意的成绩!1、常用文件操作命令以下设文件名均为csp,需要复制或修改成的文件名均为rp。功能......
  • 信息学奥赛初赛天天练-91-CSP-S2023基础题3-编译命令、树的重心、拓扑排序、进制转换
    PDF文档公众号回复关键字:202409172023CSP-S选择题1单项选择题(共15题,每题2分,共计30分:每题有且仅有一个正确选项)11以下哪个命令,能将一个名为main.cpp的C++源文件,编译并生成一个名为main的可执行文件?()Ag++-omainmain.cppBg++-omain.cppmainCg++......
  • 201909-2 小明种苹果(续)ccfcsp
    一道简单的模拟。。。includeincludeusingnamespacestd;intmain(){constintN=1010;booldrop[N]={false};intn,m,i,j,cnt=0,cnt1=0;cin>>n;inty;intsum=0,sum1,temp=0;intindex;for(i=0;i<n;i++){ sum1=0;scanf("%d",&m);for(j=0;j&......
  • 历年CSP-J初赛真题解析 | 2019年CSP-J初赛阅读程序(16-33)
    学习C++从娃娃抓起!记录下CSP-J备考学习过程中的题目,记录每一个瞬间。附上汇总贴:历年CSP-J初赛真题解析|汇总_热爱编程的通信人的博客-CSDN博客#include<cstdio>#include<cstring>usingnamespacestd;charst[100];intmain(){scanf("%s",st);intn......
  • CSP 初赛要点复习
    位运算逻辑与、按位与之类的东西是不同的!“逻辑”的是判断两个数都不为\(0\),“按位”的是判断两个数的每一个二进制位与的结果,是不同的。其他运算也类似。运算符优先级如图所示:注意,~和!是同级的。加法位运算表示:a+b=(a^b)+((a&b)<<1)。与的符号开口向下,和交集的符号\(......
  • 『模拟赛』CSP-S加赛1
    Rank一般A.小W与伙伴招募仔细想了想,发现是贪心题。赛时想了跟正解完全有些不太一样的做法,被顶针说假了,但其实开了longlong能有80pts。后来发现如果思路正确打\(\mathcal{O(nm)}\)的暴力能有95pts。《对于60%的数据》考虑正解的贪法,每天相当于将第\(i\)宝石......
  • 202312-2 因子化简ccfcsp
    常规质数因子带相关资料抄写稍加修改指数的筛选部分includeinclude<math.h>typedeflonglongll;usingnamespacestd;boolisprime(lln){inti;if(n<=1)returnfalse;intsq=(int)sqrt(1.0n);for(i=2;i<=sq;i++){if(n%i==0)returnfalse;}returntrue;}cons......
  • 2024CSP-J初赛全真模拟卷选择题篇(原创,难度偏简单)
    注意,本卷由再临TSC原创,禁止转载!本卷难度偏简单,若想要通过初赛本卷应拿80+分左右查看答案的方法:if(设备=="PC"){    把光标移到答案上面,选中答案,就会显示();}elseif(设备==移动端b||设备==平板){    把答案复制,找到随便一个地方粘贴即可();}else{......
  • 信息学奥赛初赛天天练-90-CSP-S2023基础题2-离散数学、染色、完全三叉树、平面图、边
    PDF文档公众号回复关键字:202409152023CSP-S选择题1单项选择题(共15题,每题2分,共计30分:每题有且仅有一个正确选项)6以下连通无向图中,()一定可以用不超过两种颜色进行染色A完全三叉树B平面图C边双连通图D欧拉图7最长公共子序列长度常常用来衡量两个序列的相......