ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

2022.7.14 模拟赛

2022-07-14 18:31:29  阅读:139  来源: 互联网

标签:cnt ch 14 int read 1ll tag 2022.7 模拟


目录

2022.7.14 模拟赛

\(\to\text{link}\leftarrow\)

数独

思路

大模拟

\(40min\) 写完调完,难度一般般

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

inline int read(){
	int x=0,f=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
	while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}

char a[20][20];
int s[10][10];
int t[101][10][10];

inline void check_1(int x,int y,int k){
	for(int i=1;i<=9;++i)
		if(s[x][i]==k){puts("Error:row!");return;}
	for(int i=1;i<=9;++i)
		if(s[i][y]==k){puts("Error:column!");return;}
	int a=(x-1)/3*3+1,b=(y-1)/3*3+1;
	for(int i=a;i<=a+2;++i)
		for(int j=b;j<=b+2;++j)
			if(s[i][j]==k){puts("Error:square!");return;}
	s[x][y]=k;
	puts("OK!");
	return;
}

inline void check_2(int x,int y){
	bool vis[10]={0};
	int cnt=0;
	for(int i=1;i<=9;++i) vis[s[x][i]]=vis[s[i][y]]=1;
	int a=(x-1)/3*3+1,b=(y-1)/3*3+1;
	for(int i=a;i<=a+2;++i)
		for(int j=b;j<=b+2;++j)
			vis[s[i][j]]=1;
	for(int i=1;i<=9;++i) if(!vis[i]) ++cnt;
	cout<<cnt<<endl;
	for(int i=1;i<=9;++i) if(!vis[i]) cout<<i<<endl;
	return;
}

bool l[10][10],c[10][10],u[10][10];

inline void comb(int x,int y){
	memset(l,0,sizeof(l));
	memset(c,0,sizeof(c));
	memset(u,0,sizeof(u));
	memset(s,0,sizeof(s));
	int cnt1=0,cnt2=0;
	for(int i=1;i<=9;++i)
		for(int j=1;j<=9;++j){
			int a=t[x][i][j],b=t[y][i][j];
			if(a&&!s[i][j]&&!l[i][a]&&!c[j][a]&&!u[(i-1)/3*3+(j-1)/3+1][a]){
				l[i][a]=c[j][a]=u[(i-1)/3*3+(j-1)/3+1][a]=1;
				++cnt1;s[i][j]=a;
			}
			else if(b&&!s[i][j]&&!l[i][b]&&!c[j][b]&&!u[(i-1)/3*3+(j-1)/3+1][b]){
				l[i][b]=c[j][b]=u[(i-1)/3*3+(j-1)/3+1][b]=1;
				++cnt2;s[i][j]=b;
			}
		}
	cout<<cnt1<<" "<<cnt2<<endl;
}

signed main(){
	for(int i=1;i<=19;++i)
		for(int j=1;j<=19;++j){
			cin>>a[i][j];
			if(i%2==1||j%2==1) continue;
			s[i/2][j/2]=a[i][j]-'0';
		}
	int T=read();
	for(int q=1;q<=T;++q){
		string A;
		cin>>A;
		int x,y,k;
		if(A[0]=='I'){
			x=read(),y=read(),k=read();
			if(s[x][y]) puts("Error!");
			else check_1(x,y,k);
		}
		if(A[0]=='D'){
			x=read(),y=read();
			if(!s[x][y]) puts("Error!");
			else{s[x][y]=0;puts("OK!");}
		}
		if(A[0]=='Q'){
			x=read(),y=read();
			if(s[x][y]) puts("Error!");
			else check_2(x,y);
		}
		if(A[0]=='M'){x=read(),y=read();comb(x,y);}
		if(A[0]=='P'){
			for(int i=1;i<=19;++i){
				for(int j=1;j<=19;++j){
					if(isdigit(a[i][j])) cout<<s[i/2][j/2];
					else cout<<a[i][j];
				}
				cout<<endl;
			}
		}
		memcpy(t[q],s,sizeof(s));
	}
}

分糖果

思路

看到这个式子:

\[c_i=\left\{\begin{aligned}&a_1+b_1\qquad &i=1\\&\max\{c_{i-1},\sum_{j=1}^ia_i\}+b_i\qquad &1< i\le n\end{aligned}\right. \]

看到 \(1\le n\le 10^5\)

显然不能 \(dp\),显然可以贪心

直接分析 \(c_1\) 和 \(c_2\)

\[c_2=\max\{c_1,a_1+a_2\}+b_2=\max\{a_1+b_1,a_1+a_2\}+b_2=a_1+b_2+\max\{b_1,a_2\} \]

那么如果 \(i\) 在 \(j\) 前,则有

\[a_i+b_j+\max\{b_i,a_j\}<b_i+a_j+\max\{b_j,a_i\} \]

排序+贪心即可

此题做完了

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

const int N=1e6+5;

#define ll long long
#define int long long

inline int read(){
	int x=0,f=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
	while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}

int n;
struct man{
	int a,b;
	inline bool operator < (const man X) const{
		return a+X.b+max(b,X.a)<X.a+b+max(X.b,a);
	}
}d[N];
ll s[N],c[N];

signed main(){
	int T=read();
	while(T--){
		n=read();
		for(int i=1;i<=n;++i)
			d[i].a=read(),d[i].b=read();
		sort(d+1,d+n+1);
		c[1]=d[1].a+d[1].b;
		for(int i=1;i<=n;++i) s[i]=s[i-1]+1ll*d[i].a;
		for(int i=2;i<=n;++i){
			c[i]=max(c[i-1],s[i])+1ll*d[i].b;
		}
		printf("%lld\n",c[n]);
	}
}

维修机器人

思路

不同的 \(h\) 最多 \(1000\) 个,\(1\le n\le 5\times 10^4\)

计算一下,\(1000\times 5\times 10^4=5\times 10^7\),可以直接离散化,上 \(O(1000\cdot n)\) 的\(dp\)

下面只阐述单调不下降的 \(dp\) 方法,单调不上升同理

设 \(f_{i,j}\) 表示保证前 \(i\) 个有序的情况下最后一个数为 \(j\),\(g_{i}\) 表示\(\min_{j=1}^if_{i-1,j}\)

那么可以得到:

\[f_{i,j}=\left\{\begin{aligned}&g_j+m_1\qquad &j>a_i\\&g_j\qquad &j=a_i\\&g_j+m_2\qquad &j<a_i\end{aligned}\right. \]

做完了

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

const int N=5e4+1;

#define re register

inline int read(){
	int x=0,f=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
	while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}

int n,m1,m2;
int a[N];

namespace qaq{
	int f[N][1002],g[1002];
	int b[N],c[N],cnt;
	int ans=1e9;
	inline void lsh(){
		memcpy(b,a,sizeof(a));
		sort(b+1,b+n+1);
		c[++cnt]=b[1];
		for(re int i=2;i<=n;++i)
			if(b[i]!=b[i-1]) c[++cnt]=b[i];
		for(re int i=1;i<=n;++i)
			a[i]=lower_bound(c+1,c+cnt+1,a[i])-c;
	}
	inline void pre1(){
		memset(f,0x3f,sizeof(f));
		memset(g,0x3f,sizeof(g));
		f[1][a[1]]=0;
		for(re int i=a[1]-1;i;--i) f[1][i]=m2;
		for(re int i=a[1]+1;i<=cnt;++i) f[1][i]=m1;
		g[1]=f[1][1];
		for(re int i=2;i<=cnt;++i) g[i]=min(g[i-1],f[1][i]);
	}
	inline void pre2(){
		memset(f,0x3f,sizeof(f));
		memset(g,0x3f,sizeof(g));
		f[1][a[1]]=0;
		for(re int i=a[1]-1;i;--i) f[1][i]=m2;
		for(re int i=a[1]+1;i<=cnt;++i) f[1][i]=m1;
		g[cnt]=f[1][cnt];
		for(re int i=cnt-1;i;++i) g[i]=min(g[i+1],f[1][i]);
	}
	inline void dp(){
		pre1();
		for(re int i=2;i<=n;++i){
			for(re int j=1;j<=cnt;++j)
				f[i][j]=g[j];
			for(re int j=1;j<=cnt;++j){
				if(j>a[i]) f[i][j]+=m1;
				if(j<a[i]) f[i][j]+=m2;
			}
			memset(g,0x3f,sizeof(g));
			g[1]=f[i][1];
			for(re int j=1;j<=cnt;++j)
				g[j]=min(f[i][j],g[j-1]);
		}
		for(re int i=1;i<=cnt;++i) ans=min(ans,f[n][i]);
	}
	inline void solve(){
		lsh();
		dp();
		reverse(a+1,a+n+1);
		dp();
		cout<<ans<<endl;
	}
}

signed main(){
	n=read(),m1=read(),m2=read();
	for(int i=1;i<=n;++i){
		a[i]=read();
	}
	qaq::solve();
}

小乔

思路

最终的答案应该等于 \(\sum_{i=1}^m\text{覆盖点}\ i\ \text{的半径的第}\ k\ \text{大值}^2\)

首先的想法是按照半径从大到小枚举,因为每个地方最多只会被覆盖一次,我们就找到能将当前点覆盖的第 \(k\) 次是什么时候,这时就是该点所求的值

因此我们需要边修改 (区间加) 边查询 (区间第一次大于等于 \(k\) 的数字个数) 并且将已经统计过的点打标记

看到 \(1\le m\le 10^5\) 这不分块吗?

考虑用分块维护上述操作

时间复杂度 \(O(2\cdot m\sqrt{2\cdot m})\) (因为点是从 \(-m\sim m\) 编号)

注意细节:题目中 \(s_i\) 可能大于 \(t_i\),此时需要分段统计

\(yysy\),这题细节真滴多,考场上没看到 \(s_i\) 可能大于 \(t_i\) 只拿了 \(60pts\) \(qwq\)

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

const int N=1e5+5;

#define int long long

inline int read(){
	int x=0,f=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
	while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}

int n,m,k,q,sz;
int tag[500],v[N*2],bl[N*2],L[500],R[500],mn[500];
bool vis[N*2];
int cnt[500][N];
long long ans;

struct opt{
	int r,s,t;
	inline bool operator < (const opt x){
		return r>x.r;
	}
}a[N];

inline void solve(int x,int y,int val){
	if(y<x) return;
	int l=bl[x],r=bl[y];
	if(l==r){
		for(int i=x;i<=y;++i){
			if(vis[i]||(mn[l]!=-1&&v[i]>=mn[l])) continue;
			--cnt[l][v[i]];
			++v[i];
			if(v[i]+tag[l]>=k){
				vis[i]=1;
				ans+=1ll*val*1ll*val;
				continue;
			}
			++cnt[l][v[i]];
		}
		if(cnt[l][k-tag[l]]){
			ans+=1ll*cnt[l][k-tag[l]]*1ll*val*1ll*val;
			cnt[l][k-tag[l]]=0;
			mn[l]=min(mn[l],k-tag[l]);
		}
		return;
	}
	for(int i=x;i<=R[l];++i){
		if(vis[i]||(mn[l]>=0&&v[i]>=mn[l])) continue;
		--cnt[l][v[i]];
		++v[i];
		if(v[i]+tag[l]>=k){
			vis[i]=1;
			ans+=1ll*val*val;
			continue;
		}
		++cnt[l][v[i]];
	}
	for(int i=L[r];i<=y;++i){
		if(vis[i]||(mn[r]>=0&&v[i]>=mn[r])) continue;
		--cnt[r][v[i]];
		++v[i];
		if(v[i]+tag[r]>=k){
			vis[i]=1;
			ans+=1ll*val*1ll*val;
			continue;
		}
		++cnt[r][v[i]];
	}
	if(cnt[l][k-tag[l]]){
		ans+=1ll*cnt[l][k-tag[l]]*1ll*val*1ll*val;
		cnt[l][k-tag[l]]=0;
		mn[l]=min(mn[l],k-tag[l]);
	}
	if(cnt[r][k-tag[r]]){
		ans+=1ll*cnt[r][k-tag[r]]*1ll*val*1ll*val;
		cnt[r][k-tag[r]]=0;
		mn[r]=min(mn[r],k-tag[r]);
	}
	for(int i=l+1;i<=r-1;++i){
		++tag[i];
		if(cnt[i][k-tag[i]]){
			ans+=1ll*cnt[i][k-tag[i]]*1ll*val*1ll*val;
			cnt[i][k-tag[i]]=0;
			mn[i]=min(mn[i],k-tag[i]);
		}
	}
}

signed main(){
	n=read(),m=read(),k=read();
	memset(mn,0x3f,sizeof(mn));
	for(int i=1;i<=n;++i){
		a[i].r=read(),a[i].s=read(),a[i].t=read();
	}
	q=m;
	m=m*2;
	sz=sqrt(m);
	for(int i=1;i<=m;++i){
		bl[i]=(i-1)/sz+1;
		++cnt[bl[i]][0];
		if(bl[i]!=bl[i-1]) L[bl[i]]=i,R[bl[i-1]]=i-1;
	}
	R[bl[m]]=m;
	sort(a+1,a+n+1);
	for(int i=1;i<=n;++i){
		if(a[i].s>a[i].t){
			solve(a[i].s+q+1,m,a[i].r);
			solve(1,a[i].t+q,a[i].r);
		}
		else solve(a[i].s+q+1,a[i].t+q,a[i].r);
	}
	printf("%lld",ans);
}

标签:cnt,ch,14,int,read,1ll,tag,2022.7,模拟
来源: https://www.cnblogs.com/into-qwq/p/16478891.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有