Codeforces Round 918 (Div. 4)

Codeforces Round 918 (Div. 4)

D:本题从实现上来说正难则反,应该倒着做

在我正着做的时候,由于在访问后面元素的时候没有判边界,导致数组越界,出现奇怪字符在最后答案中。

int n, m; int a[N]; bool check(char c){ if(c=='a'||c=='e')return true; else return false; } void solve(){ cin>>n; string s;cin>>s; string ans; string tmp="."; for(int i=0;i<n;){ //cerr<<i<<" "; if(check(s[i])==0){ if(i)ans+=tmp; ans+=s[i];ans+=s[i+1]; if(check(s[i+2])==0){ if(check(s[i+3])){ i+=2; } else { //if(i+2>=n) if(i+2<n)ans+=s[i+2]; i+=3; /// cerr<<ans<<endl; } } else { i+=2; } } //cerr<<i<<endl; //ans+=tmp; } //cerr<<ans.size(); cout<<ans<<endl; }

E题:给定数组,问是否存在一段连续子数组满足奇数项的和等于偶数项。

Solution1:我们可以不去考虑奇偶性,而去考虑前缀和.-我们令原数组偶数项全部变为相反数,如果出现前缀和之前出现过或者为0,则存在
Solution2:对奇数位置和偶数位置做前缀和,分别记作p1,p2。

限制条件变成p1[R]p1[L1]==p2[R]p2[L1]

交换位置,p2[L1]p1[L1]==p2[R]p1[R]

把所有位置的 {奇偶前缀和之差,位置} 存入set 枚举L,在set里面二分找合法的R即可

void solve(){ cin>>n; for(int i=1;i<=n;i++)cin>>a[i]; set<int>s; int sum=0; s.insert(0LL); for(int i=1;i<=n;i++){ if(i%2){ sum+=a[i]; } else { sum-=a[i]; } if(s.count(sum)){ cout<<"YES"<<endl; return ; } else s.insert(sum); } cout<<"NO"<<endl; }

F:需要找到起点在自己后面,但是终点在自己前面的人的数量

Solution:对起点排序,省去一维,只看终点在自己前面的人,按照上述方式,我们需要倒着遍历。实现上由于值域很大,我们需要保序离散化。对于每个人的贡献由于需要动态加点和区间和查询,使用树状数组维护。
//每次要找到在排序后的a[i]的后面并且第二维小于b[i]的数需要,需要动态添加 //不能提前排序无法区分,使用树状数组 void solve(){ // cin>>n; // vector<int>v; // for(int i=1;i<=n;i++){ // int x,y;cin>>x>>y; // a[i]={x,y}; // v.push_back(y); // } // sort(v.begin(),v.end()); // for(auto x:v)cerr<<x<<" "; // cerr<<endl; // sort(a+1,a+1+n); // int ans=0; // //题目保证不重复 // for(int i=1;i<=n;i++){ // int val=a[i].second; // int pos=lower_bound(v.begin(),v.end(),val)-v.begin()+1; // ans+=pos-i; // cerr<<a[i].first<<" "; // cerr<<val<<" "<<pos-1<<endl; // } // cout<<ans<<endl; cin>>n; vector<int>ls; //这里需要有序离散化 Fenwick<int>c(n+1); for(int i=1;i<=n;i++){ int x,y; cin>>x>>y; ls.push_back(y); a[i]={x,y}; } sort(ls.begin(),ls.end()); auto id=[&](int x){ int pos=lower_bound(ls.begin(),ls.end(),x)-ls.begin()+1; return pos; }; //每个数关注比自己起点大的数的终点是不是比自己小 sort(a+1,a+1+n); int ans=0; for(int i=n;i>=1;i--){ auto [x,y]=a[i]; y=id(y); ans+=c.sum(y); c.add(y,1); } cout<<ans<<endl; }

G:求从1-n的最短路,特别的是加入自行车限制,在每个点可以选择使用当前点的自行车,或者继续使用自己之前的自己车,不同车对边权影响。

Solution:从思想上来说可以从分层图上理解,多加一维实现自行车的转移。也有人说就是二维dijstra,因为算法的正确性保证是在此基础上。对于当前每个点我们可以选择换城市不换自行车,或者换车不换城市(只能一次)
int n, m; int a[N]; //dij加一维状态表示自行车信息 struct edge{int v,w;}; vector<edge>e[N]; void solve(){ cin>>n>>m; for(int i=1;i<=n;i++)e[i].clear(); vector<int>s(n+1); for(int i=1;i<=m;i++){ int u,v,w;cin>>u>>v>>w; e[u].push_back({v,w}); e[v].push_back({u,w}); } for(int i=1;i<=n;i++)cin>>s[i]; priority_queue<a3, vector<a3>, greater<a3>>q; vector<vector<int>>dis(n+1,vector<int>(n+1,1e18)); vector<vector<bool>>vis(n+1,vector<bool>(n+1,0)); q.push({0,1,1}); dis[1][1]=0; while(q.size()){ auto [d,u,b]=q.top();q.pop(); if(vis[u][b]==true)continue; vis[u][b]=true; for(auto [v,w]:e[u]){ if(dis[v][b]>d+w*s[b]){ dis[v][b]=d+w*s[b]; q.push({dis[v][b],v,b}); } } if(b!=u){ q.push({d,u,u}); dis[u][u]=d; } } cout << *min_element(dis[n].begin() + 1, dis[n].begin() + n); cout<<endl; }

__EOF__

本文作者爱飞鱼
本文链接https://www.cnblogs.com/mathiter/p/18111391.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   potential-star  阅读(50)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示