Codeforces Round #857 Div.1/Div.2 CF1801/1802 2A~2F 题解
Div 2A. Likes
如果要赞最多,肯定是先放所有的点赞,再放所有移除的操作。如果要最少,那就先把赞分成两种:最后被移除的和没被移除的;最后先放所有被移除的,放一个移除一个,然后再把所有没被移除的接在最后即可。
时间复杂度\(O(n)\)。
点击查看代码
#include <bits/stdc++.h>
#define rep(i,n) for(int i=0;i<n;++i)
#define repn(i,n) for(int i=1;i<=n;++i)
#define LL long long
#define fi first
#define se second
#define pb push_back
#define mpr make_pair
void fileio()
{
#ifdef LGS
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
}
void termin()
{
#ifdef LGS
std::cout<<"\n\nEXECUTION TERMINATED";
#endif
exit(0);
}
using namespace std;
int t,n,a[110],ans1[110],ans2[110];
int main()
{
fileio();
cin>>t;
rep(tn,t)
{
cin>>n;
int posi=0,nega=0;
rep(i,n) cin>>a[i];
rep(i,n) if(a[i]>0) ++posi;else ++nega;
int bigp=posi,bign=nega,smlp=posi,smln=nega,ansbig=0,anssml=0;
repn(i,n)
{
if(bigp)
{
--bigp;
++ansbig;
}
else
{
--bign;
--ansbig;
}
if(i<=nega*2)
{
if(i%2==1) ++anssml;
else --anssml;
}
else ++anssml;
ans1[i]=ansbig;ans2[i]=anssml;
}
repn(i,n) cout<<ans1[i]<<' ';cout<<endl;
repn(i,n) cout<<ans2[i]<<' ';cout<<endl;
}
termin();
}
Div 2B. Settlement of Guinea Pigs
对每个时刻求出可能需要的最大猪圈数,然后取max即可。对于一个时刻,可以把猪分成两类,已经认证性别的和没认证的。没认证的只能自己住一个猪圈,因为和任意其他猪住一个都可能不合法。已经认证的,如果总数是>0的偶数,肯定是两类都是奇数个的情况最费猪圈;如果是奇数,那就是一类奇数一类偶数,猪圈数是固定的;总数是0那就是0个猪圈。
时间复杂度\(O(n)\)。
点击查看代码
#include <bits/stdc++.h>
#define rep(i,n) for(int i=0;i<n;++i)
#define repn(i,n) for(int i=1;i<=n;++i)
#define LL long long
#define fi first
#define se second
#define pb push_back
#define mpr make_pair
void fileio()
{
#ifdef LGS
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
}
void termin()
{
#ifdef LGS
std::cout<<"\n\nEXECUTION TERMINATED";
#endif
exit(0);
}
using namespace std;
int t,n,a[100010];
int calc(int pre)
{
if(pre==0) return 0;
if(pre==1) return 1;
if(pre==2) return 2;
if(pre%2==0) return (pre-2)/2+2;
return (pre+1)/2;
}
int main()
{
fileio();
cin>>t;
rep(tn,t)
{
cin>>n;
int pre=0,nxt=0,ans=0;
rep(i,n)
{
int x;scanf("%lld",&x);
if(x==1)
{
++nxt;
ans=max(ans,nxt+calc(pre));
}
else
{
pre+=nxt;nxt=0;
ans=max(ans,calc(pre));
}
}
cout<<ans<<endl;
}
termin();
}
Div 1A/2C. The Very Beautiful Blanket
怎么每场都有猜谜题呢。。。
首先猜一个:不同数的最大个数是n*m,很多这种题都是先猜能达到最大值的
观察题目中的那个两个田字格异或和相等的限制,其实只要对\(2^0\cdots 2^{63}\)的每个bit都满足就行了。对于每个bit,发现如果我们只把一些行中所有的数都刷上这个bit,其他的行不刷,是满足限制的。比如我们令第1,3,5,6行所有的数都含有\(2^3\),其他的行都不含有,是符合限制的,这时每个田字格的异或和都是0。发现使用这种刷一行或一列的方式,我们可以让矩阵中的所有数都不同。比如我们令数组\(a=\{0,1,2,\cdots 9\},b=\{10,11,12\cdots 19\}\)。矩阵中第i行j列的数含有\(2^{a_k}\)当且仅当i中含有\(2^k\),含有\(2^{b_k}\)当且仅当j中含有\(2^k\)。这么操作其实就是给一些行和一些列都刷上了某一个bit,且成功区别开了所有行和所有列,使得矩阵中每一个数都不同。
时间复杂度\(O(nmlognlogm)\)。
点击查看代码
#include <bits/stdc++.h>
#define rep(i,n) for(int i=0;i<n;++i)
#define repn(i,n) for(int i=1;i<=n;++i)
#define LL long long
#define fi first
#define se second
#define pb push_back
#define mpr make_pair
void fileio()
{
#ifdef LGS
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
}
void termin()
{
#ifdef LGS
std::cout<<"\n\nEXECUTION TERMINATED";
#endif
exit(0);
}
using namespace std;
int t,n,m,ans[210][210];
vector <int> r,c;
int main()
{
fileio();
rep(i,10) r.pb(1<<i);
for(int i=10;i<20;++i) c.pb(1<<i);
cin>>t;
rep(tn,t)
{
cin>>n>>m;
rep(i,n) rep(j,m)
{
ans[i][j]=0;
rep(k,r.size()) if(i&(1<<k)) ans[i][j]|=r[k];
rep(k,c.size()) if(j&(1<<k)) ans[i][j]|=c[k];
}
cout<<n*m<<endl;
rep(i,n)
{
rep(j,m) printf("%d ",ans[i][j]);
puts("");
}
}
termin();
}
Div 1B/2D. Buying gifts
先把所有department按\(a_i\)从小到大排序,枚举给第一个人买的礼物最大值\(a_i\),此时i右侧的必须全买给第二个人,左侧的可以给第一个人也可以给第二个人。首先令i右侧的\(b_i\)最大值为\(mx\),如果\(mx\ge a_i\),此时的答案就是\(mx-a_i\);否则可以在i左侧的\(b_i\)中找一个与\(a_i\)最接近的再次更新答案,可以用multiset实现。需要特判一下\(i=n\)的情况。
时间复杂度\(O(nlogn)\)。
点击查看代码
#include <bits/stdc++.h>
#define rep(i,n) for(int i=0;i<n;++i)
#define repn(i,n) for(int i=1;i<=n;++i)
#define LL long long
#define pii pair <LL,LL>
#define fi first
#define se second
#define pb push_back
#define mpr make_pair
void fileio()
{
#ifdef LGS
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
}
void termin()
{
#ifdef LGS
std::cout<<"\n\nEXECUTION TERMINATED";
#endif
exit(0);
}
using namespace std;
LL t,n;
vector <pii> a;
multiset <LL> l,r;
LL findNearL(LL x)
{
auto it=l.lower_bound(x);
pii ret=mpr(1e18,1e18);
if(it!=l.end()) ret=min(ret,mpr(llabs(*it-x),*it));
if(it!=l.begin())
{
--it;
ret=min(ret,mpr(llabs(*it-x),*it));
}
return ret.se;
}
int main()
{
fileio();
cin>>t;
rep(tn,t)
{
cin>>n;
a.clear();
LL x,y;
rep(i,n)
{
scanf("%lld%lld",&x,&y);
a.pb(mpr(x,y));
}
sort(a.begin(),a.end());
l.clear();r.clear();
rep(i,a.size()) r.insert(a[i].se);
LL ans=1e18;
rep(i,a.size())
{
r.erase(r.lower_bound(a[i].se));
if(i-1>=0) l.insert(a[i-1].se);
if(i==a.size()-1) break;
LL mx2=*r.rbegin();
ans=min(ans,llabs(mx2-a[i].fi));
if(mx2<a[i].fi&&l.size())
{
LL val=findNearL(a[i].fi);
ans=min(ans,llabs(val-a[i].fi));
}
}
LL val=findNearL(a.back().fi);
ans=min(ans,llabs(val-a.back().fi));
cout<<ans<<endl;
}
termin();
}
Div 1C/2E. Music Festival
首先令\(mx_i\)表示第i个专辑中的最大值,发现如果一个mx小的专辑排在一个mx大的专辑后面(mx相等也一样),那这个专辑是不能产生任何贡献的。所以可以先把所有专辑按\(mx_i\)从小到大排序,我们现在要在其中选一些使得前缀最大值的个数最多。可以用dp实现,\(dp_{i,j}\)表示处理到第i个专辑,此时被选的专辑中mx的最大值为j的最大前缀最大值个数。这状态是\(O(n^2)\)的,但是在处理每个i时改变的状态数都很少,所以可以用线段树维护j这一维,转移时枚举当前专辑中得到的前缀最大值个数,就能得到可以从其转移的j的范围,在线段树上询问即可。注意事项:每个测试点不能直接清空整个线段树,会TLE,要先把值域离散化后清空要用的部分。
时间复杂度\(O(nlogn)\)。
点击查看代码
#include <bits/stdc++.h>
#define rep(i,n) for(int i=0;i<n;++i)
#define repn(i,n) for(int i=1;i<=n;++i)
#define LL long long
#define fi first
#define se second
#define pb push_back
#define mpr make_pair
void fileio()
{
#ifdef LGS
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
}
void termin()
{
#ifdef LGS
std::cout<<"\n\nEXECUTION TERMINATED";
#endif
exit(0);
}
using namespace std;
int t,n;
vector <pair <int,vector <int> > > v;
vector <int> dsc;
int getDSC(int x){return lower_bound(dsc.begin(),dsc.end(),x)-dsc.begin();}
namespace st
{
int n2,dat[800010];
void upd(int k,int val)
{
dat[k]=max(dat[k],val);
while(k>0)
{
k=(k-1)/2;
dat[k]=max(dat[k],val);
}
}
int qry(int k,int lb,int ub,int tlb,int tub)
{
if(ub<tlb||tub<lb) return 0;
if(tlb<=lb&&ub<=tub) return dat[k];
return max(qry(k+k+1,lb,(lb+ub)/2,tlb,tub),qry(k+k+2,(lb+ub)/2+1,ub,tlb,tub));
}
}
int main()
{
fileio();
cin>>t;
rep(tn,t)
{
cin>>n;
v.clear();dsc.clear();
rep(i,n)
{
int x,y,mx=-1e9;vector <int> tmp;
scanf("%d",&x);
rep(j,x)
{
scanf("%d",&y);
mx=max(mx,y);tmp.pb(y);dsc.pb(y);
}
v.pb(mpr(mx,tmp));
}
sort(v.begin(),v.end());
sort(dsc.begin(),dsc.end());dsc.erase(unique(dsc.begin(),dsc.end()),dsc.end());
rep(i,v.size()) rep(j,v[i].se.size()) v[i].se[j]=getDSC(v[i].se[j]);
st::n2=1;while(st::n2<dsc.size()) st::n2*=2;
rep(i,st::n2*2+3) st::dat[i]=0;
rep(i,v.size())
{
vector <int> premx;
int mx=-1;
rep(j,v[i].se.size()) if(v[i].se[j]>mx)
{
mx=v[i].se[j];
premx.pb(mx);
}
int opt=-1;
rep(i,premx.size())
{
int lb=(i==0 ? 0:premx[i-1]),ub=premx[i]-1;
int val=st::qry(0,0,st::n2-1,lb,ub)+premx.size()-i;
opt=max(opt,val);
}
st::upd(premx.back()+st::n2-1,opt);
}
cout<<st::dat[0]<<endl;
}
termin();
}
Div 1D/2F. The way home
无论是cf还是atc,这种用比较复杂的状态跑最短路的题还是经常有的。
先明确我们走的思路:当要坐某趟航班钱不够时,就在我们走到过的报酬最高的城市不断补表演,直到钱够做这次航班为止。
令\(dist_{i,j}\)表示当前走到i号点,在这次走到i号点之前经过的\(w\)最大的点的编号为j,此时的最小表演数和最大剩余钱数(先按最小表演数从小到大排序,相同的再按剩余钱数从大到小排序)。我们来证明:如果\(dist_{i,j}\)有两个可能的状态\(\{a,b\}\)和\(\{c,d\}\)(ac表示最小表演数,bd表示钱数),且a<c,b<d,此时第一个状态一定优于第二个。用一种类似归纳的思想,我们假设已经对这两个状态转移过来的路径上的所有\(dist_{i,j}\)都证明了其最优状态唯一。由于这两个状态在这次到i之前经过的报酬最高的点都是j,因此它们是从同一个\(dist_{j,*}\)转移过来的,在那之后它们的表演数才变得不同。因此第二个状态的d肯定\(<w_j\),因为我们补表演是补到能坐航班就停了,所以剩下的一定\(<w_j\)。因此如果给第一个状态补\(c-a\)次表演,使两个状态表演次数相同,第一个的钱数一定比第二个多,所以第一个一定更优。
然后就用上面的状态跑一个Dijkstra就行了,时间复杂度\(O(nmlog(n^2))\)(可能?没仔细算)。
点击查看代码
#include <bits/stdc++.h>
#define rep(i,n) for(int i=0;i<n;++i)
#define repn(i,n) for(int i=1;i<=n;++i)
#define LL long long
#define pii pair <LL,LL>
#define fi first
#define se second
#define pb push_back
#define mpr make_pair
void fileio()
{
#ifdef LGS
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
}
void termin()
{
#ifdef LGS
std::cout<<"\n\nEXECUTION TERMINATED";
#endif
exit(0);
}
using namespace std;
LL t,n,m,p,w[810];
vector <pii> g[810];
pii dist[810][810];
priority_queue <pair <pii,pii> > q;
int main()
{
fileio();
cin>>t;
rep(tn,t)
{
cin>>n>>m>>p;
repn(i,n) scanf("%lld",&w[i]);
rep(i,n+3) g[i].clear();
LL x,y,z;
rep(i,m)
{
scanf("%lld%lld%lld",&x,&y,&z);
g[x].pb(mpr(y,z));
}
rep(i,n+3) rep(j,n+3) dist[i][j]=mpr(-1e18,-1e18);
dist[1][0]=mpr(0,p);
q.push(mpr(mpr(0,p),mpr(1,0)));
while(!q.empty())
{
auto fr=q.top();q.pop();
pii val=fr.fi;LL pos=fr.se.fi,opt=fr.se.se;
if(dist[pos][opt]>val) continue;
if(w[pos]>w[opt]) opt=pos;
rep(i,g[pos].size())
{
pii nval=val;
if(nval.se<g[pos][i].se)
{
LL add=(g[pos][i].se-nval.se+w[opt]-1)/w[opt];
nval.fi-=add;nval.se+=add*w[opt];
}
nval.se-=g[pos][i].se;
if(dist[g[pos][i].fi][opt]<nval)
{
dist[g[pos][i].fi][opt]=nval;
q.push(mpr(nval,mpr(g[pos][i].fi,opt)));
}
}
}
pii ans=mpr(-1e18,-1e18);
repn(i,n) ans=max(ans,dist[n][i]);
if(ans.fi< -1e17) puts("-1");
else cout<< -ans.fi<<endl;
}
termin();
}
由于我用小号打的Div2,所以看不到过了一车的那个1F,1E也不会。后面如果有时间会更新1E和1F的题解
Codeforces Round #857 Div.1/Div.2 CF1801/1802 2A~2F 题解的更多相关文章
- Educational Codeforces Round 60 (Rated for Div. 2) - C. Magic Ship
Problem Educational Codeforces Round 60 (Rated for Div. 2) - C. Magic Ship Time Limit: 2000 mSec P ...
- Educational Codeforces Round 60 (Rated for Div. 2) - D. Magic Gems(动态规划+矩阵快速幂)
Problem Educational Codeforces Round 60 (Rated for Div. 2) - D. Magic Gems Time Limit: 3000 mSec P ...
- Educational Codeforces Round 43 (Rated for Div. 2)
Educational Codeforces Round 43 (Rated for Div. 2) https://codeforces.com/contest/976 A #include< ...
- Educational Codeforces Round 35 (Rated for Div. 2)
Educational Codeforces Round 35 (Rated for Div. 2) https://codeforces.com/contest/911 A 模拟 #include& ...
- Codeforces Educational Codeforces Round 44 (Rated for Div. 2) F. Isomorphic Strings
Codeforces Educational Codeforces Round 44 (Rated for Div. 2) F. Isomorphic Strings 题目连接: http://cod ...
- Codeforces Educational Codeforces Round 44 (Rated for Div. 2) E. Pencils and Boxes
Codeforces Educational Codeforces Round 44 (Rated for Div. 2) E. Pencils and Boxes 题目连接: http://code ...
- Educational Codeforces Round 63 (Rated for Div. 2) 题解
Educational Codeforces Round 63 (Rated for Div. 2)题解 题目链接 A. Reverse a Substring 给出一个字符串,现在可以对这个字符串进 ...
- Educational Codeforces Round 39 (Rated for Div. 2) G
Educational Codeforces Round 39 (Rated for Div. 2) G 题意: 给一个序列\(a_i(1 <= a_i <= 10^{9}),2 < ...
- Educational Codeforces Round 48 (Rated for Div. 2) CD题解
Educational Codeforces Round 48 (Rated for Div. 2) C. Vasya And The Mushrooms 题目链接:https://codeforce ...
- Educational Codeforces Round 60 (Rated for Div. 2) 题解
Educational Codeforces Round 60 (Rated for Div. 2) 题目链接:https://codeforces.com/contest/1117 A. Best ...
随机推荐
- 肖sir__面试第十天课程__模拟面试讲解
一.面对面模拟面试1.打印好简历2.带好手机,录制自己回答的问题,总结,反思(内部),关闭手机和闹钟(外部)3.有笔试题,可以拍照发群里4.可以携带耳塞(适合女生)5.语速流程6.礼貌用语(面试官好, ...
- Nmap常见命令
一测试环境 靶机:metasploitable2-linux [下载地址] IP:192.168.88.128 攻击机: kali IP :192.168.88..131 二 Nmap命令 ...
- 第八章 mysql的主从复制
mysql的主从复制 一 主从复制搭建 1. 准备三台主机 (这个是多实例) 3307 master3308 salve13309 salve2 2. master 节点设置 [mysqld] lo ...
- Python学习笔记之7.5 - 定义有默认参数的函数》》》直接在函数定义中给参数指定一个默认值,默认参数的值应该是不可变的对象
问题: 你想定义一个函数或者方法,它的一个或多个参数是可选的并且有一个默认值. 解决方案: 定义一个有可选参数的函数是非常简单的,直接在函数定义中给参数指定一个默认值,并放到参数列表最后就行了.例如: ...
- VSCode STM32跨平台开发环境搭建
VSCode的强大不用多说了,直接上教程: 一.到官网下载安装VSCode 二.安装完成后,打开VSCode,安装PlatformIO IDE 插件 三.安装完重启VSCode,VSCode会继续安装 ...
- 【2020NIO.AC省选模拟#10】C. 寄蒜几盒
题目链接 原题解: 可以发现,假设我们把凸多边形看做障碍,一个点没有被染色当且仅当在它的位置上能看到凸多边形任意两条相对的边中的一条(也就是能看到至少$\dfrac{n}{2}$条边). 对于每个询问 ...
- iOS开发--APP性能检测方案汇总
1 . CPU 占用率 CPU作为手机的中央处理器,可以说是手机最关键的组成部分,所有应用程序都需要它来调度运行,资源有限.所以当我们的APP因设计不当,使 CPU 持续以高负载运行,将会出现APP卡 ...
- ELK收集njinx
前提:安装elk 1.yum安装nginx 2.修改配置文件 vim /etc/nginx/nginx.conf.d 3.重新启动 nginx -s reload 4.安装压测命令 压测文件 5.写完 ...
- MBR与GPT[转]
MBR分区 MBR的意思是"主引导记录",是IBM公司早年间提出的.它是存在于磁盘驱动器开始部分的一个特殊的启动扇区. 这个扇区包含了已安装的操作系统系统信息,并用一小段代码来启动 ...
- 基于 Docker 安装 Nginx 搭建静态服务器
最近一直在准备家里的服务器部署一个自己用的网站玩玩,一来是用来学习部署的基础知识,二来,后面有空学点前端,可以部署到自己网站玩玩. 参考链接:https://juejin.cn/post/705740 ...