Codeforces Round 938 (Div. 3)
鲜花
卡在
A
题意
一堆酸奶,买一个花费
Sol
如果一次性买两个更划算肯定要尽量多的一次性买两个,分开买划算就一个一个买。
Code
#include<bits/stdc++.h>
#define ll long long
#define N 200005
#define endl "\n"
#define fi fisrt
#define se second
using namespace std;
const ll mod=1e9+7;
const ll inf=1e18;
const double eps=1e-6;
ll n,a,b;
void sol(){
cin>>n>>a>>b;
if(a*2<b)b=a*2;
if(n&1)cout<<(n/2)*b+a<<endl;
else cout<<(n/2)*b<<endl;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
ll ttt;
cin>>ttt;
while(ttt--)sol();
return 0;
}
B
题意
大小为
给定
Sol
然后竖着放,和横着类似,
具体来说开个桶,桶为空就是找不到。
最后在检查一下是否所有位置都满足即可。
Code
#include<bits/stdc++.h>
#define ll long long
#define N 2005
#define endl "\n"
#define fi fisrt
#define se second
using namespace std;
const ll mod=1e9+7;
const ll inf=1e18;
const double eps=1e-6;
ll a[N*N];
ll f[N][N];
map<ll,ll>mp;
ll n,c,d;
void sol(){
cin>>n>>c>>d;
mp.clear();
for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)f[i][j]=0;
for(int i=1;i<=n*n;i++){
cin>>a[i];
mp[a[i]]++;
}
sort(a+1,a+n*n+1);
f[1][1]=a[1];
for(int i=1;i<n;i++){
if(mp[f[1][i]+d]){
mp[f[1][i]+d]--;
f[1][i+1]=f[1][i]+d;
}else{
cout<<"No\n";
return ;
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<n;j++){
if(mp[f[j][i]+c]){
mp[f[j][i]+c]--;
f[j+1][i]=f[j][i]+c;
}else{
cout<<"No\n";
return ;
}
}
}
for(int i=2;i<=n;i++){
for(int j=2;j<=n;j++){
if(f[i][j]!=f[i-1][j]+c){
cout<<"No\n";
return ;
}
if(f[i][j]!=f[i][j-1]+d){
cout<<"No\n";
return ;
}
}
}
cout<<"Yes\n";
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
ll ttt;
cin>>ttt;
while(ttt--)sol();
return 0;
}
C
题意
长为
求删除了多少个数。
Sol
用
对于 :
若
若
对于 :
若
若
特别的,对于
花费
结束条件
这些操作能过进行,需要
最后的答案是
Code
#include<bits/stdc++.h>
#define ll long long
#define N 200005
#define endl "\n"
#define fi fisrt
#define se second
using namespace std;
const ll mod=1e9+7;
const ll inf=1e18;
const double eps=1e-6;
ll n,k,a[N];
void sol(){
cin>>n>>k;
for(int i=1;i<=n;i++)cin>>a[i];
ll l=1,r=n,now=0;
while(l<=r&&k>0){
if(l==r){
if(k>=a[l])cout<<n<<endl;
else cout<<n-1<<endl;
return ;
}
if(now==0){
if(a[l]<=a[r]){
if(k<a[l]*2-1)break;
k-=a[l]*2-1;
a[r]-=a[l]-1;
now=1;
l++;
continue;
}
if(a[l]>a[r]){
if(k<a[r]*2)break;
k-=a[r]*2;
a[l]-=a[r];
now=0;
r--;
continue;
}
}
if(now==1){
if(a[l]>=a[r]){
if(k<a[r]*2-1)break;
k-=a[r]*2-1;
a[l]-=a[r]-1;
now=0;
r--;
continue;
}
if(a[l]<a[r]){
if(k<a[l]*2)break;
k-=a[l]*2;
a[r]-=a[l];
now=1;
l++;
continue;
}
}
}
cout<<n-(r-l+1)<<endl;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
ll ttt;
cin>>ttt;
while(ttt--)sol();
return 0;
}
D
题意
求长为
Sol
动态维护以
类似滑动窗口,每次右移开头减去旧开头的贡献,加上新末尾的贡献。
具体来说就是开个桶
然后对比
Code
#include<bits/stdc++.h>
#define ll long long
#define N 1000005
#define endl "\n"
#define fi fisrt
#define se second
using namespace std;
const ll mod=1e9+7;
const ll inf=1e18;
const double eps=1e-6;
map<ll,ll> mp,cnt;
ll n,m,a[N],k,res,now;
bool vis[N];
void sol(){
res=0,now=0;
cin>>n>>m>>k;
mp.clear();
cnt.clear();
for(int i=1;i<=n;i++){
cin>>a[i];
vis[i]=0;
}
for(int i=1;i<=m;i++){
ll x;
cin>>x;
mp[x]++;
}
for(int i=1;i<=n;i++){
cnt[a[i]]++;
if(cnt[a[i]]<=mp[a[i]])now++;
if(i<m)continue;
if(now>=k)res++;
cnt[a[i-m+1]]--;
if(cnt[a[i-m+1]]<mp[a[i-m+1]])now--;
}
cout<<res<<endl;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
ll ttt;
cin>>ttt;
while(ttt--)sol();
return 0;
}
E
题意
01
串,找到最大的 01
串可以全变成
Sol
首先明确一下如何取反区间比较容易判断。从最左边开始遍历,如果当前位置是
然后根据数据范围来看算法大概是
枚举所有长为
还是类似滑动窗口的思想,动态维护
对于一次循环,依次进行如下判断:
若
若
两个判断对
取最大的
Code
#include<bits/stdc++.h>
#define ll long long
#define N 800005
#define endl "\n"
#define fi fisrt
#define se second
using namespace std;
const ll mod=1e9+7;
const ll inf=1e18;
const double eps=1e-6;
map<ll,ll> mp;
ll n,fl[N];
bool vis[N];
string s,t;
void sol(){
cin>>n>>s;
s=" "+s;
for(int p=n;p>=1;p--){
ll cnt=0;
for(int i=1;i<=n;i++)vis[i]=0;
int i=1;
for(i=1;i+p-1<=n;i++){
ll t=s[i]-'0';
if(t^cnt==0){
cnt^=1;
vis[i]=1;
}
if(i>=p&&vis[i-p+1])cnt^=1;
}
ll fl=0;
for(;i<=n;i++){
ll t=s[i]-'0';
if(t^cnt==0){
fl=1;
break;
}
if(i>=p&&vis[i-p+1])cnt^=1;
}
if(fl==0){
cout<<p<<endl;
return ;
}
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
ll ttt;
cin>>ttt;
while(ttt--)sol();
return 0;
}
F
题意
Sol
本题的关键在于凑偶数。
注意到面值为
然后默认
Code
#include<bits/stdc++.h>
#define ll long long
#define N 800005
#define endl "\n"
#define fi fisrt
#define se second
using namespace std;
const ll mod=1e9+7;
const ll inf=1e18;
const double eps=1e-6;
ll a[7];
void sol(){
cin>>a[1]>>a[2]>>a[3]>>a[4];
ll res=a[4]/2;
res+=a[1]/2+a[2]/2+a[3]/2;
if((a[1]&1)&&(a[2]&1)&&(a[3]&1))res++;
cout<<res<<endl;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
ll ttt;
cin>>ttt;
while(ttt--)sol();
return 0;
}
G
题意
Sol
记
得卡卡常,不然被 hack 得很惨。
Code
#include<bits/stdc++.h>
#define ll long long
#define N 205
#define endl "\n"
#define fi first
#define se second
using namespace std;
const ll mod=1e9+7;
const ll inf=1e18;
const double eps=1e-6;
ll n,m;
ll a[N][N];
bool vis[N*N];
ll w;
queue<pair<ll,ll> >q;
bool bfs(ll x,ll y,ll p){
while(!q.empty())q.pop();
q.push({x,y});
vis[(x-1)*m+y]=1;
while(!q.empty()){
auto t=q.front();
q.pop();
vis[(t.fi-1)*m+t.se]=0;
if(t.fi==n&&t.se==m)return 1;
for(int i=1;i<=2;i++){
ll nx=t.fi+(i==1);
ll ny=t.se+(i==2);
if(nx>n)continue;
if(ny>m)continue;
if(vis[(nx-1)*m+ny]||a[nx][ny]%p)continue;
q.push({nx,ny});
vis[(nx-1)*m+ny]=1;
}
}
return 0;
}
vector<ll>v;
bool cmp(ll x,ll y){
return x>y;
}
void sol(){
v.clear();
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>a[i][j];
}
}
w=__gcd(a[1][1],a[n][m]);
int i=1;
for(i=1;i*i<w;i++){
if(w%i==0){
v.push_back(w/i);
v.push_back(i);
}
}
if(i*i==w)v.push_back(i);
sort(v.begin(),v.end(),cmp);
for(auto i:v){
if(bfs(1,1,i)){
cout<<i<<endl;
return ;
}
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
ll ttt;
cin>>ttt;
while(ttt--)sol();
return 0;
}
H
题意
每秒防御塔会对其范围内的所有敌人造成
定义攻击范围内的点需要满足的条件是:
敌人的基础生命为
Sol
注意到虽然敌人不只有一个,但是所有敌人的受攻击情况是相同的,所以只对一个敌人分析。
我们可以在最坏
具体来说,我们将所有路径上的点保存下来,然后枚举塔和路径上的点,令
然后
但是我们还要对敌人血量增加
然后这玩意要和
其中
然后就是求右边那坨的最大值,特别的注意到如果起副作用,也就是小于零,不如让其攻击距离为零,所以要保证每个位置非负。
然后问题就变成了 P4014 分配问题 。
但是不会费用流,所以剩下的部分没写,详情参照如上题目题解。
Code
提供一下求
#include<bits/stdc++.h>
#define ll long long
#define x1 xx
#define y1 yy
#define dl double
#define N 55
#define endl "\n"
#define fi first
#define se second
using namespace std;
const ll mod=1e9+7;
const ll inf=1e18;
const double eps=1e-6;
ll n,m,k;
struct pt{
ll x,y;
};
ll a[N][N],f[N*N][30];
ll upz(pt i,pt j){
dl x1=i.x;
dl x2=j.x;
dl y1=i.y;
dl y2=j.y;
dl res1=sqrt(((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)));
ll res2=ceil(res1);
return res2;
}
vector<pt>v;
ll res=0;
void work(ll x,ll y,ll z,ll id){
ll mx=0;
for(auto i:v){
ll t=upz({x,y},i);
mx=max(t,mx);
f[id][t]+=z;
}
for(int i=1;i<=mx;i++){
f[id][i]+=f[id][i-1];
}
ll x3=1;
for(int i=0;i<=mx;i++){
f[id][i]=max(f[id][i]-x3,0ll);
cout<<f[id][i]<<" ";
x3*=3;
}
cout<<endl;
}
void sol(){
res=0;
v.clear();
cin>>n>>m>>k;
for(int i=1;i<=k;i++)for(int j=0;j<=25;j++)f[i][j]=0;
for(int i=1;i<=n;i++){
string s;
cin>>s;
s=" "+s;
for(int j=1;j<=m;j++){
a[i][j]=(s[j]=='#');
if(s[j]=='#')v.push_back({i,j});
}
}
for(int i=1;i<=k;i++){
ll x,y,z;
cin>>x>>y>>z;
work(x,y,z,i);
}
m=0;
cout<<endl;
}
int main(){
ll ttt;
cin>>ttt;
while(ttt--)sol();
return 0;
}
本文作者:yshpdyt
本文链接:https://www.cnblogs.com/yshpdyt/p/18123023
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步