当前位置: 首页 > news >正文

AtCoder Beginner Contest 429(ABCDEF)

前言

感冒了状态真不行,c和d卡了半天,昨天晚上又发烧了,现在嗓子疼得一批……

一、A - Too Many Requests

#include <bits/stdc++.h>
using namespace std;/*   /\_/\
*   (= ._.)
*   / >  \>
*/#define dbg(x) cout<<#x<<" "<<x<<endl
#define vdbg(a) for(auto x:a) cout<<x<<" ";cout<<endl
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;void solve()
{int n,m;cin>>n>>m;for(int i=1;i<=n;i++){if(i<=m){cout<<"OK"<<endl;}else{cout<<"Too Many Requests"<<endl;}}
}signed main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int t=1;//cin>>t;while(t--){solve();    }return 0;
}

这个题还是很简单的,就是分小于等于m和大于m讨论一下即可。

二、B - N - 1

#include <bits/stdc++.h>
using namespace std;/*   /\_/\
*   (= ._.)
*   / >  \>
*/#define dbg(x) cout<<#x<<" "<<x<<endl
#define vdbg(a) for(auto x:a) cout<<x<<" ";cout<<endl
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;void solve()
{int n,m;cin>>n>>m;vector<int>a(n+1);int sum=0;for(int i=1;i<=n;i++){cin>>a[i];sum+=a[i];}for(int i=1;i<=n;i++){if(sum-a[i]==m){cout<<"Yes"<<endl;return ;}}cout<<"No"<<endl;
}signed main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int t=1;//cin>>t;while(t--){solve();    }return 0;
}

这个题就是先统计一下整体累加和,再逐个判断移除每个位置后的累加和是否等于m即可。

三、C - Odd One Subsequence

以前的c有这么难吗,调了半天才调出来……

#include <bits/stdc++.h>
using namespace std;/*   /\_/\
*   (= ._.)
*   / >  \>
*/#define dbg(x) cout<<#x<<" "<<x<<endl
#define vdbg(a) for(auto x:a) cout<<x<<" ";cout<<endl
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;void solve()
{int n;cin>>n;vector<int>a(n+1);for(int i=1;i<=n;i++){cin>>a[i];}vector<ll>pre(n+1);ll sum=0;ll ans=0;for(int i=1;i<=n;i++){ll cnt=pre[a[i]];ll diff=i-1-cnt;    ans+=cnt*diff;ll cur=(cnt-1)*cnt/2;if(sum>cur){ans+=sum-cur;}pre[a[i]]++;if(pre[a[i]]>=2){sum-=(cnt-1)*cnt/2;sum+=(pre[a[i]]-1)*pre[a[i]]/2;}}cout<<ans<<endl;
}signed main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int t=1;//cin>>t;while(t--){solve();    }return 0;
}

对于某个位置上的数x,能形成的合法三元组的个数,可以从前面所有和x相同的数里选一个,再从前面所有和x不同的数里选一个组成,也可以从前面每个和x不同的数里都选出两个组成。第一种情况好求,重点是第二种情况。那么可以考虑维护出前缀中从每种数中选两个的总方案数,那么每次只需要扣去从当前数x中选两个的情况,之后再更新即可。

byd其实根本不用这么麻烦,直接遍历一遍统计词频,再枚举从当前数里选两个,再从和当前数不同的所有数里选一个即可。反正a[i]小于等于n,根本没必要写的这么麻烦……

四、D - On AtCoder Conference

感觉这题也写复杂了……

#include <bits/stdc++.h>
using namespace std;/*   /\_/\
*   (= ._.)
*   / >  \>
*/#define dbg(x) cout<<#x<<" "<<x<<endl
#define vdbg(a) for(auto x:a) cout<<x<<" ";cout<<endl
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;int bs(ll v,int l,vector<ll>&a)
{int r=a.size();int m;int ans=0;while(l<=r){m=l+r>>1;if(a[m]>=v){ans=m;r=m-1;}else{l=m+1;}}return ans;
}void solve()
{ll n,m,c;cin>>n>>m>>c;vector<ll>a(n+1);for(int i=1;i<=n;i++){cin>>a[i];}   sort(a.begin()+1,a.end());vector<ll>cnts;vector<ll>pos;for(int i=1;i<=n;i++){int j=i+1;while(j<=n&&a[j]==a[i]){j++;}cnts.push_back(j-i);pos.push_back(a[i]);i=j-1;}int len=cnts.size();for(int i=0;i<len;i++){cnts.push_back(cnts[i]);}len<<=1;for(int i=1;i<len;i++){cnts[i]+=cnts[i-1];}ll ans=0;for(int i=0;i<len/2;i++){int p=bs(c+cnts[i],i,cnts);ll cur=cnts[p]-cnts[i];if(i+1<len/2){ll cnt=pos[i+1]-pos[i];ans+=cur*cnt;}else{ll cnt=m-(pos[i]-pos[0]);ans+=cur*cnt;}}cout<<ans<<endl;
}signed main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int t=1;//cin>>t;while(t--){solve();    }return 0;
}

因为这个问题是环,所以还是考虑将其多抄一遍转化成链,然后存一下每个位置的人数并求前缀和。那么对于当前出发点i,就可以直接去二分大于等于cnts[i]+c的最左位置即可。之后注意到m非常大,所以肯定不能直接开m长度的数组,所以还是要考虑对其进行离散化,那么就把下标和m有关转化成和n有关了。

代码就是先从小到大排序,然后统计每个位置上的人数,多抄一遍并统计前缀和。之后注意到,对于离散化后的相邻两个有人的位置,中间所有没人的位置的答案都和前一个有人的位置一样,所以还需要多记录一个pos表存每个有人的位置。所以答案就是相邻两个有人位置的间距乘以从这个位置开始经过的人数即可。

五、E - Hit and Away

#include <bits/stdc++.h>
using namespace std;/*   /\_/\
*   (= ._.)
*   / >  \>
*/#define dbg(x) cout<<#x<<" "<<x<<endl
#define vdbg(a) for(auto x:a) cout<<x<<" ";cout<<endl
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;const int MAXN=2e5+5;int n,m;vector<vector<int>>g(MAXN);//from[u]:离u最近和第二近的安全点
vector<array<int,2>>from(MAXN,{-1,-1});
//dis[u]:离u最近和第二近的安全点的距离
vector<array<int,2>>dis(MAXN,{-1,-1});void solve()
{cin>>n>>m;for(int i=1,u,v;i<=m;i++){cin>>u>>v;g[u].push_back(v);g[v].push_back(u);}string s;cin>>s;s=" "+s;queue<pii>q;for(int i=1;i<=n;i++){if(s[i]=='S'){q.push({i,0});//自己from[i][0]=i;dis[i][0]=0;}}while(!q.empty()){auto cur=q.front();q.pop();int u=cur.first;int o=cur.second;for(auto v:g[u]){//没有最近点if(dis[v][0]==-1){dis[v][0]=dis[u][o]+1;from[v][0]=from[u][o];q.push({v,0});}//没有次近点且v的最近点和次近点不相同else if(dis[v][1]==-1&&from[v][0]!=from[u][o]){dis[v][1]=dis[u][o]+1;from[v][1]=from[u][o];q.push({v,1});}}}for(int i=1;i<=n;i++){if(s[i]=='D'){cout<<dis[i][0]+dis[i][1]<<endl;}}
}signed main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int t=1;//cin>>t;while(t--){solve();    }return 0;
}

这个多源bfs太妙了……

考虑设置from和dis表,分别表示离u节点最近和次近的节点以及距离。那么初始将所有安全节点的from[i][0],即最近点设置成自己,dis[i][0]设置为0,然后把(i,0)这个状态放入队列。之后定义状态(u,o)为节点u作为某个点的最近点或次近点,然后每次去看当前点的相邻节点v。若v还没有设置最近点,那么v的最近点就是u当前状态的点,否则若v没设置次近点,且v的最近点和次近点不同,那么v的次近点就是u当前状态的点。那么最后只需要输出每个危险点到其最近点和次近点的距离之和即可。

六、F - Shortest Path Query

太难了……没有任何套路,就是纯难……

#include <bits/stdc++.h>
using namespace std;/*   /\_/\
*   (= ._.)
*   / >  \>
*/#define dbg(x) cout<<#x<<" "<<x<<endl
#define vdbg(a) for(auto x:a) cout<<x<<" ";cout<<endl
#define INF 1e9
#define INFLL 1e18
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;const int MAXN=2e5+5;int g[3][MAXN];struct matrix
{int a[3][3];matrix(){for(int i=0;i<3;i++){for(int j=0;j<3;j++){a[i][j]=INF;}}}matrix operator*(const matrix&x){matrix ans;for(int i=0;i<3;i++){for(int j=0;j<3;j++){for(int k=0;k<3;k++){ans.a[i][k]=min(ans.a[i][k],a[i][j]+x.a[j][k]);}}}return ans;}//矩阵和线段树
}A[MAXN],res[MAXN<<2];void up(int i)
{//注意矩阵乘法从右往左res[i]=res[i<<1|1]*res[i<<1];
}void build(int l,int r,int i)
{if(l==r){res[i]=A[l];}else{int m=l+r>>1;build(l,m,i<<1);build(m+1,r,i<<1|1);up(i);}
}void change(int jobi,int l,int r,int i)
{if(l==r){res[i]=A[l];}else{int m=l+r>>1;if(jobi<=m){change(jobi,l,m,i<<1);}else{change(jobi,m+1,r,i<<1|1);}up(i);}
}matrix init(int i)
{int c0=g[0][i];int c1=g[1][i];int c2=g[2][i];matrix ans;ans.a[0][0]=c0?1:INF;ans.a[1][0]=c0&&c1?2:INF;ans.a[2][0]=c0&&c1&&c2?3:INF;ans.a[1][1]=c1?1:INF;ans.a[0][1]=c0&&c1?2:INF;ans.a[2][1]=c2&&c1?2:INF;ans.a[2][2]=c2?1:INF;ans.a[1][2]=c2&&c1?2:INF;ans.a[0][2]=c2&&c1&&c0?3:INF;return ans;
}void solve()
{int n;cin>>n;string s;for(int i=0;i<3;i++){cin>>s;s=" "+s;for(int j=1;j<=n;j++){g[i][j]=s[j]=='.';}}//因为只有三行,所以观察可以发现,最短路不可能向左走//所以最优路径可以通过从左往右dp一遍算出//定义dp[i][j]为从(1,1)开始走到(i,j)的最小步数//所以有//dp[1][j+1]=min(dp[1][j]+1,dp[2][j]+2,dp[3][j]+3)//dp[2][j+1]=min(dp[1][j]+2,dp[2][j]+1,dp[3][j]+2)//dp[3][j+1]=min(dp[1][j]+3,dp[2][j]+2,dp[3][j]+1)//所以这个可以描述成矩阵乘法,所以dp[n]=An*……*A1*dp[1]//若一个位置有墙,那么可以将矩阵对应位置改成无穷大,不让其转移//因为涉及单点修改,所以可以考虑用线段树维护矩阵乘法的结果//初始化每列的矩阵for(int i=1;i<=n;i++){A[i]=init(i);}build(1,n,1);int q;cin>>q;int r,c;while(q--){cin>>r>>c;r--;g[r][c]^=1;A[c]=init(c);change(c,1,n,1);int ans=res[1].a[2][0];cout<<(ans!=INF?ans-1:-1)<<endl;}
}signed main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int t=1;//cin>>t;while(t--){solve();    }return 0;
}

因为只有三行,所以观察可以发现最短路不可能向左走,所以最优路径可以通过从左往右dp一遍得到。定义dp[i][j]为从(1,1)开始走到(i,j)的最小步数,那么可以得到注释中写的转移公式。所以这个转移过程可以描述为矩阵乘法,所以就有dp[n]=A[n]*A[n-1]*……*A[1]*dp[1]。而若一个位置有墙,那么在矩阵对应位置改成无穷大即可。又因为每次修改是单点修改,所以可以考虑用线段树维护矩阵乘法的结果。

所以init函数就是通过当前第i行的状态去构造相应矩阵,注意线段树up时矩阵是从右往左乘的即可。

总结

先把身体养好再说吧……

END

http://www.dtcms.com/a/541459.html

相关文章:

  • 好用的GEO优化引擎服务商
  • 做网站那个平台网站制作网站建设案例
  • 搜索引擎主题网站模板网络架构有哪几层
  • Linux 驱动开发中,主设备号和次设备号不同的两个驱动能否正常工作
  • 人和AI的分工模式!
  • 模板网站与 定制网站的 对比中企动力主要做什么的
  • ECharts 3D柱状图组件开发实战:Bar3D.vue 完整解析
  • 手机App上的轮播图是如何实现的—探究安卓轮播图
  • Day71 MQTT数据上传与ARM端交叉编译部署全链路实践
  • 2024年 5月 每日分享
  • 漯河英文网站建设创建私人网站
  • 网站开发学哪一个好电子商务网站建设模板
  • 5.4 大数据方法论与实践指南-存储-安全合规
  • 凡科建设网站图片怎么删除专门做自由行的网站
  • 车辆智能检索与缉查布控
  • Cesium中如何修改geojson数据的颜色
  • 51c大模型~合集42
  • C++语法—类的声明和定义
  • 企业网站建设方案资讯查询公司的网站
  • 高端企业网站建设公司免费网站代理访问
  • JavaEE初阶——多线程(4)线程安全
  • 杭州网站推广营销服务深圳做美颜相机的公司
  • 什么样 个人网站 备案适合做网站的软件有哪些
  • 做设计在哪个网站上找高清图青岛做物流网站
  • 数据源切换的陷阱:Spring Boot中@Transactional与@DS注解的冲突博弈与破局之道
  • Kubernetes节点资源优化:自托管代理配置实践
  • 1688网站怎样做推广东莞市路桥收费所
  • 做网站需要用到哪些开发软件潜江资讯网信息发布
  • Day2实战-元组的基本操作
  • 01 数学建模中M的取值影响及分析