首页 > 其他分享 >CSP 加赛 1

CSP 加赛 1

时间:2024-09-15 12:14:36浏览次数:7  
标签:string int sum tot id cost 加赛 CSP

A.小W与伙伴招募

考虑贪心,可以发现,每一天只需要优先选择价值低的即可

这种贪心思路有一个错误的扩展,就是先把 \(m\) 天的货一次性补齐再一次性买,这样做的问题在于有可能买到次日的货,而这样做是不被允许的

考虑放到线段树上,维护 “节点能够提供的钻石数量” 和 “节点花费” 两个值,只要我们保证价格在线段树上递增排列(这是很好做到的,排序再建树即可),那么我们就可以通过和平衡树类似的二分来向下递归

  • 如果左子树满足当前要求,直接在左子树里买
  • 否则,先把左子树买完,再在右子树里买

然后考虑怎么维护这两个值

每次补货只能单点修改,复杂度显然太高了,因此,我们设计节点数量 \(t=kb_i+s\),其中 \(b_i\) 为 \(i\) 的每日补货数量,这样我们在每一天新开始的时候,只需要让所有的 \(k\) 都增加 \(1\) 就可以了,而这在线段树上是容易实现的

介于我们并不能同时维护加和乘,所以开两棵线段树(当然也可以合成一颗,不过两者的维护是完全没有关系的),然后在父结点上维护子节点权值和即可

还有问题就是怎么在补货之后比较快地实现 pushdown,可以在外面开两个前缀和来实现(分别对应两颗线段树)

然后是 lazytag,针对本题需要开两个 tag,一个维护补货时候的 k 增量,一个维护买了东西以后的整体清空,执行的时候先清空再增,注意顺序

\(-1\) 直接赋成 \(1e6\) 就行了

另外需要注意的就是,不要直接对 \(m\) 建树,可以考虑微调一下 sort,让价值相同的中,数量最多的排在前面,然后你只要遇到一个 \(-1\) 就说明你一直买这个就行了(后面的都更贵),因此直接对此时的 \(i\) 建树就行了

不过我不明白为啥对 \(m\) 建树会导致答案错掉

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
template<typename T>
void read(T& x){
	x=0;bool sym=0;char c=getchar();
    while(!isdigit(c)){sym^=(c=='-');c=getchar();}
    while(isdigit(c)){x=x*10+c-48;c=getchar();}
    if(sym)x=-x;
}
template<typename T,typename... Args>
void read(T& x,Args&... args){
    read(x);read(args...);
}
#define int long long
struct tree{
	int l,r;
	int tot_sum,cost_sum;
	int lazy_cover,lazy_k;
}t[200001*4];
int tot_sum[200001],cost_sum[200001];
struct item{
	int a,b;
	bool operator <(const item &A)const{
		if(a==A.a) return b>A.b;
		return a<A.a;
	}
}w[200001];
#ifndef TOOL_H
#define TOOL_H
#endif
template<typename T>
T floor_sqrt(T x,T l=1,T r=-1){
	if(r==-1) r=x;
	int ans=-1;
	while(l<=r){
		int mid=(l+r)/2;
		if(mid*mid<=x){
			l=mid+1;
			ans=mid;
		}
		else{
			r=mid-1;
		}
	}
	return ans;
}
void print(__int128 x,bool first=true){
	if(x<0){
		putchar('-');
		print(-x,false);
		return;
	}
	if(x==0){
		if(first) putchar('0');
		return;
	}
	print(x/10,false);
	putchar((int)(x%10)+'0');
}
template<typename T>
std::string to_string(T x){
	std::string res;bool f=false;
	if(x<0){
		f=true;
		x*=-1;
	}
	while(x){
		res.push_back((int)(x%10)+'0');
		x/=10;
	}
	reverse(res.begin(),res.end());
	if(f) res.push_back('-');
	if(res.empty()) res.push_back('0');
	return res;
}
long long to_number(std::string x){
	long long res=0;bool f=false;
	for(int i=0;i<=(int)x.length()-1;++i){
		if(x[i]=='-'){
			f=true;
		}
		else{
			res=res*10+x[i]-'0';
		}
	}
	return res*(f?-1:1);
}
/*------TOOL_H------*/
#define tol (id*2)
#define tor (id*2+1)
#define mid(l,r) mid=((l)+(r))/2
void build(int id,int l,int r){
	t[id].l=l;
	t[id].r=r;
	if(l==r) return;
	int mid(l,r);
	build(tol,l,mid);
	build(tor,mid+1,r);
}
void update(int id){
	t[id].tot_sum=t[tol].tot_sum+t[tor].tot_sum;
	t[id].cost_sum=t[tol].cost_sum+t[tor].cost_sum;
}
void pushdown_cover(int id){
	if(t[id].lazy_cover){
		t[tol].tot_sum=t[tol].cost_sum=0;
		t[tor].tot_sum=t[tor].cost_sum=0;
		t[tol].lazy_k=t[tor].lazy_k=0;
		t[tol].lazy_cover=t[tor].lazy_cover=1;
		t[id].lazy_cover=0;
	}
}
void pushdown_k(int id){
	if(t[id].lazy_k){
		t[tol].tot_sum+=t[id].lazy_k*(tot_sum[t[tol].r]-tot_sum[t[tol].l-1]);
		t[tor].tot_sum+=t[id].lazy_k*(tot_sum[t[tor].r]-tot_sum[t[tor].l-1]);
		t[tol].cost_sum+=t[id].lazy_k*(cost_sum[t[tol].r]-cost_sum[t[tol].l-1]);
		t[tor].cost_sum+=t[id].lazy_k*(cost_sum[t[tor].r]-cost_sum[t[tor].l-1]);
		t[tol].lazy_k+=t[id].lazy_k;
		t[tor].lazy_k+=t[id].lazy_k;
		t[id].lazy_k=0;
	}
}
void change(int id,int k){
	if(k>0){
		t[id].tot_sum+=(tot_sum[t[id].r]-tot_sum[t[id].l-1]);
		t[id].cost_sum+=(cost_sum[t[id].r]-cost_sum[t[id].l-1]);
		t[id].lazy_k+=k;
	}
	else{
		t[id].tot_sum=0;
		t[id].cost_sum=0;
		t[id].lazy_k=0;
		t[id].lazy_cover=1;
	}
}
int ask(int id,int k){
	if(t[id].l==t[id].r){
		t[id].tot_sum-=k;
		t[id].cost_sum-=w[t[id].l].a*k;
		return w[t[id].l].a*k;
	}
	pushdown_cover(id);
	pushdown_k(id);
	int res=0;
	if(k<=t[tol].tot_sum){
		res=ask(tol,k);
	}
	else{
		res=t[tol].cost_sum+ask(tor,k-t[tol].tot_sum);
		change(tol,-1);
	}
	update(id);
	return res;
}
int n,m;
int c[200001];
const int inf=1e6;
signed main(){
	freopen("a.in","r",stdin);
	freopen("a.out","w",stdout);
	read(n,m);
	for(int i=1;i<=n;++i){
		read(c[i]);
	}
	for(int i=1;i<=m;++i){
		read(w[i].a,w[i].b);
		if(w[i].b==-1) w[i].b=inf;
	}
	sort(w+1,w+m+1);
	for(int i=1;i<=m;++i){
		tot_sum[i]=tot_sum[i-1]+w[i].b;
		cost_sum[i]=cost_sum[i-1]+w[i].a*w[i].b;
		if(w[i].b==inf){
			build(1,1,i);
			break;
		}
	}
	int ans=0;
	for(int i=1;i<=n;++i){
		change(1,1);
		ans+=ask(1,c[i]);
	}
	print(ans);
}

B.小W与制胡串谜题

[](string a,string b){return a+b<b+a;}

标签:string,int,sum,tot,id,cost,加赛,CSP
From: https://www.cnblogs.com/HaneDaCafe/p/18415128

相关文章

  • CSP 模拟 30
    妈妈妈妈妈妈妈妈妈妈妈妈妈妈妈妈#include<bits/stdc++.h>#defineintlonglong#definelsp<<1#definersp<<1|1#defineintlonglongtypedeflonglongll;typedefunsignedlonglongull;inlineintread(){charch=getchar();intx=0,f=1;for(;ch<'......
  • 【csp201912-2】回收站选址
    题目背景 开学了,可是校园里堆积了不少垃圾杂物。 热心的同学们纷纷自发前来清理,为学校注入正能量~题目描述通过无人机航拍我们已经知晓了n处尚待清理的垃圾位置,其中第i(1≤i≤n)处的坐标为(x,y),保证所有的坐标均为整数。我们希望在垃圾集中的地方建立些回收站。具体来说,对......
  • 信息学奥赛初赛天天练-89-CSP-S2023基础题1-linux常用命令、完全平方数、稀疏图、队列
    PDF文档公众号回复关键字:202409142023CSP-S选择题单项选择题(共15题,每题2分,共计30分:每题有且仅有一个正确选项)1在Linux系统终端中,以下哪个命令用于创建一个新的目录?()AnewdirBmkdirCcreateDmkfold2从0,1,2,3,4中选取4个数字,能组成(......
  • 南沙csp-j/s一对一家教陈老师解题:1318:【例5.3】自然数的拆分
    ​题目描述】任何一个大于1的自然数n,总可以拆分成若干个小于n的自然数之和。当n=7共14种拆分方法:7=1+1+1+1+1+1+17=1+1+1+1+1+27=1+1+1+1+37=1+1+1+2+27=1+1+1+47=1+1+2+37=1+1+57=1+2+2+27=1+2+47=1+3+37=1+67=2+2+37=2+57=3+4total=14【输入】输入n。......
  • CSP2024-19
    C题意:给定一棵树,定义简单路径\(x\toy\)是好的当且仅当\(x\)是路径中编号最小值,\(y\)是路径中编号最大值。\(n\le10^6\)。赛时双log做法:点分治,设路径端点\(x\)到分治之间的最小值为\(\min\),最大值为\(\max\)。如果\(x=\min\),A中加入二元组\((x,\max)\);\(x=......
  • 9.13 模拟赛(炼石计划 11 月 04日 CSP-S 十连测 #7)
    炼石计划11月04日CSP-S十连测#7【补题】-比赛-梦熊联盟(mna.wang)复盘基本上一眼秒了T1,先写这题。在8:30写完了对拍。用了将近一个小时。然后放到桌面2就没管,一直拍到了比赛结束。T2什么牛魔题面???出题人学过语文吗???T3把题读懂了,但是一直不能正确模拟出样例1,......
  • 南沙csp-j/s一对一家教陈老师解题:1334:【例2-3】围圈报数
    ​【题目描述】有n个人依次围成一圈,从第1个人开始报数,数到第m个人出列,然后从出列的下一个人开始报数,数到第m个人又出列,…,如此反复到所有的人全部出列为止。设n个人的编号分别为1,2,…,n,打印出列的顺序。【输入】nn和mm。【输出】出列的顺序。【输入样例】417【输出样例】......
  • CSP-J 算法基础 快速排序
    文章目录前言分治思想快速排序具体例子步骤1:选择基准值步骤2:分区步骤3:递归排序左边部分`[3,1,7,0,2]`步骤4:递归排序`[1,0,2]`步骤5:合并左边部分步骤6:合并整个数组快速排序的步骤总结:快速排序的第二个例子初始状态第一步:分区第二步:递归排序右边部分`[10,......
  • 南沙csp-j/s一对一家教陈老师解题:1317:【例5.2】组合的输出
    ​ 【题目描述】排列与组合是常用的数学方法,其中组合就是从n个元素中抽出r个元素(不分顺序且r≤n),我们可以简单地将n个元素理解为自然数1,2,…,n,从中任取r个数。现要求你用递归的方法输出所有组合。例如n=5,r=3,所有组合为:123 124 125 134 135 14......
  • 信息学奥赛初赛天天练-88-CSP-S2023阅读程序1-数据类型、unsigned 关键字、二进制、位
    信息学奥赛初赛天天练-88-CSP-S2023阅读程序1-数据类型、unsigned关键字、二进制、位运算、左移、右移、异或运算PDF文档公众号回复关键字:202409132023CSP-S阅读程序1判断题正确填√,错误填⨉;除特殊说明外,判断题1.5分,选择题3分,共计40分)01#include<iostream>......