首页 > 其他分享 >8.12模拟赛小结

8.12模拟赛小结

时间:2023-08-13 20:14:28浏览次数:49  
标签:f1 log int 线段 ans 8.12 小结 模拟 define

前言

最 ez 的一集

T1 打工 原题

化简题意:有\(n\) 个工作,每个工作有固定的工资截止时间 你可以在 \(1\) 个时间单位内选择一项工作并完成它 求最后最大工资

思考:

诶 好像做个这个题?上次似乎讲过,用反悔贪心来做

思路:

首先讲原工作的截止时间从小到大排序 然后每次遍历一个工作 如果能做就做了 如果做不了就看看之前做过的所有工作中有没有工资比当前工资低的 直接选择不做那个工作 做当前的工作即可

要快速访问一段东西的最小值 用堆优化即可

时间复杂度 \(O(n\log n)\)

Code

#include<bits/stdc++.h>
#pragma GCC optimize(3,"Ofast","inline")
#define mp make_pair
#define ll long long
#define N 2000005
using namespace std;
int n,m;
pair <ll,ll> a[N];
ll ans,last;
priority_queue<ll> q;
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)
		scanf("%lld%lld",&a[i].first,&a[i].second),a[i].second*=-1;
	sort(a+1,a+1+m);
	for(int i=1;i<=m;i++)
	{
		ll x=-a[i].second;
		last+=a[i].first-a[i-1].first;
		if(last)
		{
			ans+=x;
			q.push(-x);
			last--;
		}
		else
		{
			if(q.empty()) continue;
			int z=-q.top();
			if(x>z) ans-=z,q.pop(),ans+=x,q.push(-x);
		}
	}
	printf("%lld",ans);
	return 0;
}

T2 购物 原题

简要题意:有 \(n\) 种货币,每种货币的价值为 \(v_i\) ,你有 \(c_i\) 个,你要支付 \(m\) 元,老板每种货币有无限个,你需要满足你支出的货币数和老板找回你钱的货币数的和最小

思考:

这是一个很容易就想到的完全背包和多重背包的结合体

最难想的问题是上界

比赛时直接猜结论过了(),上界是 \(2m\) ,时间复杂度是\(O(nm\log m)\) 差不多是 \(10^8\) 过了

代码很好写 两个背包就行

难就难在验证结论的正确性

好吧我不会证明(((

看一下第一篇题解的证明吧()

Code

#include<bits/stdc++.h>
#define N 205
#define M 400005
using namespace std;
int n,m,v[N],c[N],q;
int f1[M],f2[M],ans=1e9;
inline void bag(int x,int v)
{
	for(int i=q;i>=x*v;i--)
		f1[i]=min(f1[i],f1[i-v*x]+x);
}
int main()
{
	scanf("%d%d",&n,&m);
	q=3*m;
	fill(f1,f1+q+2,1e9);
	fill(f2,f2+q+2,1e9);
	f1[0]=f2[0]=0;
	for(int i=1;i<=n;i++) 
		scanf("%d",&v[i]);
	for(int i=1;i<=n;i++) 
		scanf("%d",&c[i]);
	for(int i=1;i<=n;i++)
	{
		for(int j=v[i];j<=q-m;j++)
			f2[j]=min(f2[j],f2[j-v[i]]+1);
		int t=1;
		while(c[i]>t)
		{
			bag(t,v[i]);
			c[i]-=t;
			t*=2;
		}
		bag(c[i],v[i]);
	}
	for(int i=m;i<=q;i++)
		ans=min(ans,f1[i]+f2[i-m]);
	if(ans==1e9) ans=-1;
	cout<<ans;
	return 0;
}

水了()

T3 魔法 原题

简要题意:给 \(m\) 个字符长度为 \(n\) 可能有 ? 的 \(01\) 串 ?可以当成 01 来看 给定 \(q\) 次操作 每次会修改一个字符串或者查询区间 \(l\to r\)中有多少个字符串可以解释成该 \(01\) 串

吐槽一下: lgjOJ 的数据太辣鸡了 能开 \(30\) 棵线段树艹过去 真的无语(((

思考:不妨分类讨论

  • 如果 \(l\to r\) 某一位同时存在 \(0\) 和 \(1\) 那么肯定不合法 答案为 \(0\)
  • 如果 \(l\to r\) 某一位只有 \(0\),\(1\) 或 ? 说明这一位固定 对答案没有贡献
  • 如果 \(l\to r\) 某一位只有 ? 说明这一位可以取 \(0\),\(1\) 二者之一 对答案的贡献是 \(\times 2\)

好的我们发现这道题每一位开一棵线段树或者树状数组即可 发现 \(n\leq 30\) 直接暴艹(((

然后交到原题一看 T了(((

分析一下时间复杂度 : \(O(qn\log m) \leq 6\times 10^8\)

能艹过去就是数据水了(((

我们要考虑正解

不妨思考一下,这 \(n\) 棵线段树 每次只存 \(01\) 真的太浪费空间了

我们不妨考虑直接将他们压位压进一个 \(int\) 里

可以用这题了解压位

我们考虑 \(3\) 棵线段树:

  • \(0\)树:每个字符串\(1\to 1,0\to 0,?\to 0\)
  • \(1\)树:每个字符串\(1\to 0,0\to 1,?\to 0\)
  • \(?\)树:每个字符串\(1\to 1,0\to 1,?\to 0\)

每棵线段树存的是他们的

为什么?我们把要求的数的那一位都看成 \(0\) 了 显然只有每一位都是 \(0\) 最终的或值才是 \(0\) 然后如果 \(0\) 树和一树查询的值与一下也是 \(0\) 显然方案合法 然后查一下 ? 树区间内有几个 \(0\) 即可

每次操作一次是 \(\log m\) 的 查询一次位数是 \(O(n)\) 的

时间复杂度 \(O(q(n+\log m))\)

Code

#include<bits/stdc++.h>
#define M 100055
using namespace std;
struct segtree{
	int tr[4*M];
	inline void Pushup(int x)
	{
		tr[x]=tr[x*2]|tr[x*2+1];
	}
	inline void updata(int l,int r,int L,int x,int v)
	{
		if(l>L||r<L) return;
		if(l==r)
		{
			tr[x]=v;
			return;
		}
		int mid=(l+r)/2;
		updata(l,mid,L,x*2,v);
		updata(mid+1,r,L,x*2+1,v);
		Pushup(x);
	}
	inline int query(int l,int r,int L,int R,int x)
	{
		if(l>R||r<L) return 0;
		if(l>=L&&r<=R) return tr[x];
		int mid=(l+r)/2;
		return query(l,mid,L,R,x*2)|query(mid+1,r,L,R,x*2+1);
	}
}tr[3];
int n,m,q,ans;
string s;
inline void modify(int x,string s)
{
	int s1=0,s2=0,s3=0,t=1;
	for(int i=0;i<n;i++)
	{
		if(s[i]=='0') s2|=t,s3|=t;
		if(s[i]=='1') s1|=t,s3|=t; 
		t*=2;
	}
	tr[0].updata(1,m,x,1,s1);
	tr[1].updata(1,m,x,1,s2);
	tr[2].updata(1,m,x,1,s3);
}
inline int ask(int l,int r)
{
	int s1=tr[0].query(1,m,l,r,1);
	int s2=tr[1].query(1,m,l,r,1);
	int s3=tr[2].query(1,m,l,r,1);
	if((s1&s2)==0)
	{
		int sum=0;
		while(s3)
		{
			sum++;
			s3-=s3&-s3;
		}
		return 1<<(n-sum);
	}
	else return 0;
}
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n>>m>>q;
	for(int i=1;i<=m;i++)
	{
		cin>>s;
		modify(i,s);
	}
	while(q--)
	{
		int opr,l,r,x;
		cin>>opr;
		if(opr==0)
		{
			cin>>l>>r;
			ans^=ask(l,r);
		}
		else
		{
			cin>>x>>s;
			modify(x,s);
		}
	}
	cout<<ans;
	return 0;
}

T4 和平

日常摆烂 稳定发挥

标签:f1,log,int,线段,ans,8.12,小结,模拟,define
From: https://www.cnblogs.com/g1ove/p/17627142.html

相关文章

  • 使用夜神模拟器调试安卓apk
    安装夜神模拟器,安装后打开 进入模拟器的安装目录Nox.exe所在的目录 在此目录进入cmd  然后输入命令 1adbconnect127.0.0.1:62001 5.查看adbdevices这样就是连接成功了,就可以通过adb命令对夜神的模拟器进行编辑了 1PSD:\ProgramFiles\Nox\bin>cmd......
  • 【Java】美团8.12笔试复盘
    5道编程题2小时如果您看到哪里有问题,万望评论区指正,在此谢过!!!第一题:数组遍历importjava.util.Scanner;publicclassNextNumbers{/*题目:给你一个排列和两个数问你:这两个数在排列里是不是相邻输入:第一行:n代表排列中数的个数第二行:a1--an......
  • CSP模拟-19
    D.西安行原AGC013E思路DP.最朴素的DP是\(\Theta(n^2)\)的,考虑i是当前DP到的点,j是当前线段的起点.考虑分类讨论数据范围很抽象,所以考虑用矩阵加速。首先试着把它转换成线性的赋予它一个新的组合意义:把每条线段看作一个整体\(a_i\)因为题最后求的是\(\prod_{i=1}^{num}a_i^......
  • 8.12 2014 年 JOI 圆满结束
    稻草人按\(x\)排序,可以将问题转化为寻找点对\((i,j)\),使得\(y[i]<y[j]\)且对于所有\(i<k<j\),都不满足\(y[i]<y[k]<y[j]\)。点对问题,考虑\(CDQ\)分治。容易发现最终对点\(i\)产生贡献的\(j\)的\(y[j]\)单调递减,可以使用单调栈维护。单调栈内即是右边所有可以满......
  • 数论练习题小结
    1.P1447题意:求\[\sum\limits_{i=1}^n\sum\limits_{j=1}^m2\times(i,j)-1\]思考:原式等价于\(2\sum\limits_{i=1}^n\sum\limits_{j=1}^m(i,j)-n*m\)然后套上欧拉反演即可时间复杂度\(O(\sqrtn)\)2.P4318题意:\(T\)组数据,每组数据给出一个正整数\(K\),求第\(K\)个不含大......
  • 8.8模拟赛小结
    0.前言又是爆炸的一场T1只因数分解出题人树脂666是不是香菜逢仁鸡成分过于复杂题意:输入一个数\(n\)分解一个\(m\)定义只因数为\(x\)为\(n!\)的因数构造一种方案使得质因数小于等于\(n\)思考:要知道的是\(m\leqn!\)所以我们不妨考虑\(m\)拆成几个数倒过来思考......
  • 8.7模拟赛小结
    T1转圈圈题目大意:给你一个只含有一个\(1\)的\(01\)串\(S\)每次你可以翻转一段区间为\(k\)的子串且给出\(m\)个禁止位置必须保证\(1\)在任何时刻都不能出现在静止位置上对于每个位置\(i\)给出旋转到\(i\)位置时的最小次数无法旋转到这个位置时输出\(-1\)思考:原题要求我们......
  • 8.11模拟赛小结
    前言最无语的一集T1数对原题给定整数\(L,R\(L\\le\R)\),请计算满足以下条件的整数对\((x,y)\)的数量:\(L\\le\x,y\\le\R\)设\(g\)是\(x,y\)的最大公约数,则满足以下条件:\(g\\neq\1\)且\(\frac{x}{g}\\neq\1\)且\(\frac{y}{g}\\neq\1\)很简单的......
  • 2023.8.12
    又是一周的结束,浅浅做个总结,这周主要有三天没有在家,没带电脑,出去玩了几天,也就没学多少,主要是有时间的时候在手机上做一下pta的题目,简单看了一下那个考试题目,感觉有点困难,看来还没完全学会,下周找一些资源视频什么的看一看,这周总结大概就是这样,下周继续努力。......
  • 2023.8.12 普及月赛记录
    比赛传送门按照往常的经验,A和B应该都问题不大,而且我不注重抢什么首杀,于是这次改变策略:C\(\rightarrow\)D\(\rightarrow\)B\(\rightarrow\)A。先看C。题目:queue。嗯~不错,原来是大模拟,出题人非常的CCF。看完感觉就是简单的维护几个队列的模拟,感觉难度不大。然后感觉自......