2022.7.14 模拟赛
作者:互联网
2022.7.14 模拟赛
数独
思路:
大模拟
\(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