Codeforces Round 982 (Div. 2)(A~D1)
对dp还不是特别熟练
只做到了C(还是太菜了),开始前刚好各种事情来了,vp晚了10多分钟开才始做题,喜提排名(不是)3000+,后面有时间就尽量把dp补掉
比赛链接:https://codeforces.com/contest/2027/problem
A. Rectangle Arrangement
你需要在一个无限的方格网格上涂色,所有格子最初都是白色的。为了完成这项任务,你有
你将使用 每个 印章 恰好一次 在网格上涂一个与印章同样大小的矩形区域为黑色。你不能旋转印章,对于每个格子,印章必须完全覆盖它或者完全不覆盖它。你可以在网格上的任何位置使用印章,即使印章覆盖的一些或全部格子已经是黑色的。
在使用完所有印章之后,你能得到的黑色方格区域的 周长之和 的最小值是多少?
每个测试包含多个测试案例。第一行包含测试案例的数量 t(1≤t≤500)。每个测试案例的描述紧随其后。
每个测试案例的第一行包含一个整数 n(1≤n≤100)。
接下来的 n 行中,第 i 行包含两个整数 wi 和 hi(1≤wi,hi≤100),分别代表第 i 个印章的宽度和高度。
对于每个测试案例,输出一个整数——在使用完所有印章后,你能得到的黑色方格区域周长之和的最小值。
5
5
1 5
2 4
3 3
4 2
5 1
3
2 2
1 1
1 2
1
3 2
3
100 100
100 100
100 100
4
1 4
2 3
1 5
3 2
20
8
10
400
16
思路:这题我是老老实实进行了区域覆盖,然后dfs了一遍区域,看周长
没想到是小学数学,
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#define ll long long
#define lowbit(x) (x & -x)
//#define endl "\n"// 交互题记得删除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
ll ksm(ll x, ll y)
{
ll ans = 1;
while (y)
{
if (y & 1)
{
ans = ans % mod * (x % mod) % mod;
}
x = x % mod * (x % mod) % mod;
y >>= 1;
}
return ans % mod % mod;
}
ll gcd(ll x, ll y)
{
if (y == 0)
return x;
else
return gcd(y, x % y);
}
void fio()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
struct s
{
ll x,y;
}p[2500];
ll a[400][400];
ll d[4]={0,1,-1,0};
ll e[4]={1,0,0,-1};
int main()
{
fio();
ll t;
cin>>t;
while(t--)
{
for(ll i=1;i<=100;i++)
{
for(ll j=1;j<=100;j++)
a[i][j]=0;
}
ll n;
cin>>n;
for(ll i=1;i<=n;i++)
{
ll w,h;
cin>>w>>h;
for(ll k=1;k<=w;k++)
{
for(ll u=1;u<=h;u++)
{
a[k][u]=1;
}
}
}
ll ans=0;
for(ll i=0;i<=101;i++)
{
for(ll j=0;j<=101;j++)
{
for(ll u=0;u<=3;u++)
{
ll nx=i+d[u];
ll ny=j+e[u];
if(nx>=1&&nx<=100&&ny>=1&&ny<=100&&a[i][j]==0)
{
if(a[nx][ny])ans++;
}
}
}
}
cout<<ans<<endl;
}
}
B. Stalin Sort
斯大林排序(Stalin Sort)是一种幽默的排序算法,它不是为了正确地对元素进行排序,而是为了消除那些不在适当位置的元素,从而实现
斯大林排序的步骤如下:从数组的第二个元素开始,如果它严格小于前一个元素(忽略那些已经被删除的元素),那么就删除它。继续遍历数组,直到数组按照非递减顺序排序。例如,数组
我们定义一个数组为“易受攻击”的,如果你可以通过反复对它的任意子数组应用斯大林排序,无论需要多少次,来将其排序成非递增顺序。
给定一个包含
每个测试包含多个测试案例。第一行包含一个整数
每个测试案例的第一行包含一个整数
每个测试案例的第二行包含
保证所有测试案例中
对于每个测试案例,输出一个整数——必须从数组中移除的最小整数数量,以使其变得“易受攻击”。
6
7
3 6 4 9 2 5 2
5
5 4 4 2 2
8
2 2 4 4 6 6 10 10
1
1000
9
6 8 9 10 12 9 7 5 4
7
300000000 600000000 400000000 900000000 200000000 400000000 200000000
2
0
6
0
4
2
样例解析:
在第一个测试案例中,最优解是移除数字
在第二个测试案例中,数组已经是非递增的,所以我们不需要移除任何整数。
思路:说了这么多,其实题意等价于问第一个是不是最大的数,枚举每一个数作为第一个,前面的要全删除,然后后面比这个数大的也要删除,这样子就可以保证排序到最后可以获得不递增的排列
不妨象想想,第一个数非最大数,且后面有更大数时是无解的
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#define ll long long
#define lowbit(x) (x & -x)
//#define endl "\n"// 交互题记得删除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
ll ksm(ll x, ll y)
{
ll ans = 1;
while (y)
{
if (y & 1)
{
ans = ans % mod * (x % mod) % mod;
}
x = x % mod * (x % mod) % mod;
y >>= 1;
}
return ans % mod % mod;
}
ll gcd(ll x, ll y)
{
if (y == 0)
return x;
else
return gcd(y, x % y);
}
void fio()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
ll a[4500];
int main()
{
fio();
ll t;
cin>>t;
while(t--)
{
ll n;
cin>>n;
for(ll i=1;i<=n;i++)
{
cin>>a[i];
}
ll ans=9999999999;
for(ll i=1;i<=n;i++)
{
ll cnt=i-1;
for(ll j=i+1;j<=n;j++)
{
if(a[j]==a[i])continue;
else if(a[j]>a[i])cnt++;
}
ans=min(ans,cnt);
}
cout<<ans<<endl;
}
}
C. Add Zeros
您将获得一个最初包含
选择一个位置
在
在您想要多次执行此操作后,数组
每个测试包含多个测试用例。第一行包含测试用例的数量
每个测试用例的第一行包含
每个测试用例的第二行包含
保证所有测试用例的
对于每个测试用例,输出一个整数 —— 在执行一系列操作后,数组
4
5
2 4 6 2 5
5
5 4 4 5 1
4
6 8 2 3
1
1
10
11
10
1
样例解析:
在第一个测试用例中,我们可以先选择
在第二个测试用例中,我们可以选择
思路:其实由这个式子
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#define ll long long
#define lowbit(x) (x & -x)
//#define endl "\n"// 交互题记得删除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
ll ksm(ll x, ll y)
{
ll ans = 1;
while (y)
{
if (y & 1)
{
ans = ans % mod * (x % mod) % mod;
}
x = x % mod * (x % mod) % mod;
y >>= 1;
}
return ans % mod % mod;
}
ll gcd(ll x, ll y)
{
if (y == 0)
return x;
else
return gcd(y, x % y);
}
void fio()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
ll n;
map<ll,set<ll>>q;
map<ll,ll>op;
ll dfs(ll cnt,ll z)//记忆化?
{
if(op[cnt])
{
return op[cnt]+z;
}
ll ans=z;
for(auto j:q[cnt])
{
ans=max(ans,dfs(cnt+j-1,z+j-1));
}
op[cnt]=ans-z;
return ans;
}
ll a[450000];
int main()
{
fio();
ll t;
cin>>t;
while(t--)
{
op.clear();
cin>>n;
for(ll i=1;i<=n;i++)
{
cin>>a[i];
if(a[i]>=(n-i+1)&&i!=1)
{
q[a[i]-(n-i+1)].insert(i);
}
}
cout<<dfs(0,n)<<endl;
q.clear();
}
}
D1.The Endspeaker (Easy Version)
这是这个问题的简单版本。唯一的区别是在这个版本中,你只需要输出操作的最小总成本。你必须解决两个版本才能进行hack。
你给定了一个长度为
类型
类型
你需要最小化使数组
每个测试包含多个测试用例。第一行包含测试用例的数量
每个测试用例的第一行包含两个整数
每个测试用例的第二行包含
每个测试用例的第三行包含
同时保证对于所有
保证所有测试用例中
对于每个测试用例,如果有可能使数组
如果没有任何操作序列可以使数组
5
4 2
9 3 4 3
11 7
1 2
20
19 18
10 2
2 5 2 1 10 3 2 9 9 6
17 9
10 11
2 2 2 2 2 2 2 2 2 2
20 18 16 14 12 10 8 6 4 2 1
1 6
10
32 16 8 4 2 1
1
-1
2
10
4
样例解析:
在第一个测试用例中,一个产生总成本为
执行类型
执行类型
执行类型
执行类型
数组
在第二个测试用例中,由于
思路:二维dp+二分前缀优化,设
这里给出优化掉第二个二维数组的方法,设二分的位置位r
则有
然后每次走完时得进行一次循环
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#define ll long long
#define lowbit(x) (x & -x)
//#define endl "\n"// 交互题记得删除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
ll ksm(ll x, ll y)
{
ll ans = 1;
while (y)
{
if (y & 1)
{
ans = ans % mod * (x % mod) % mod;
}
x = x % mod * (x % mod) % mod;
y >>= 1;
}
return ans % mod % mod;
}
ll gcd(ll x, ll y)
{
if (y == 0)
return x;
else
return gcd(y, x % y);
}
void fio()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
ll a[450000];
ll b[450000];
ll c[450000];
ll pre[450000];
int main()
{
fio();
ll t;
cin>>t;
while(t--)
{
ll n,m;
cin>>n>>m;
ll dp[n+5][m+5];
ll cnt=0;
memset(dp,0x3f3f3f3f3f3f,sizeof dp);
for(ll i=1;i<=n;i++)cin>>a[i],cnt=max(cnt,a[i]),pre[i]=pre[i-1]+a[i];
for(ll j=1;j<=m;j++)cin>>b[j],c[j]=0,dp[0][j]=0;
if(b[1]<cnt)
{
cout<<-1<<endl;
}
else
{
for(ll i=1;i<=m;i++)
{
ll cnt=0;
for(ll j=1;j<=n;j++)
{
if(a[j]>b[i])cnt++;
}
c[i]=cnt;
}
for(ll i=1;i<=m;i++)
{
ll pd=0;
ll cnt=0;
ll sum=0;
for(ll j=1;j<=n;j++)
{
if(cnt==c[i])pd=1;
if(pd==0)
{
if(a[j]>b[i])cnt++;
}
else
{
ll l=0,r=j;
while(l<r)
{
ll mid=(l+r)>>1;
if(pre[j]-pre[mid]<=b[i])
{
r=mid;
}
else
l=mid+1;
}
dp[j][i]=min({dp[j][i],dp[r][i]+m-i,dp[j][i-1],dp[r][i-1]+m-i});
}
}
for(ll j=1;j<=n;j++)
{
dp[j][i]=min(dp[j][i-1],dp[j][i]);
}
}
cout<<(dp[n][m]==0x3f3f3f3f3f3f?-1:dp[n][m])<<endl;
}
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!