其他分享
首页 > 其他分享> > 2022.7.14 模拟赛

2022.7.14 模拟赛

作者:互联网

目录

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