Codeforces Round #790 (Div. 4) A-H
Codeforces Round #790 (Div. 4) A-H
A
题目
https://codeforces.com/contest/1676/problem/A
题解
思路
知识点:模拟。
照着模拟(细节加0防炸char,虽然这里没用)。
时间复杂度 \(O(1)\)
空间复杂度 \(O(1)\)
代码
#include <bits/stdc++.h>
using namespace std;
int main(){
std::ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t;
cin>>t;
while(t--){
string s;
cin>>s;
if(0+s[0]+s[1]+s[2] == 0+s[3]+s[4]+s[5]) cout<<"YES"<<'\n';
else cout<<"NO"<<'\n';
}
return 0;
}
B
题目
https://codeforces.com/contest/1676/problem/B
题解
思路
知识点:贪心。
所有数减去最小的加在一起就行。
时间复杂度 \(O(n)\)
空间复杂度 \(O(n)\)
代码
#include <bits/stdc++.h>
using namespace std;
int a[57];
int main(){
std::ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t;
cin>>t;
while(t--){
int n;
cin>>n;
int ans = 0,mincnt = 1e8;
for(int i = 0;i<n;i++){
cin>>a[i];
mincnt = min(mincnt,a[i]);
ans += a[i];
}
ans -= n * mincnt;
cout<<ans<<'\n';
}
return 0;
}
C
题目
https://codeforces.com/contest/1676/problem/C
题解
思路
知识点:暴力。
(看错题浪费20分钟写成求全部字符串变成一样的最小次数。。。)
直接暴力求最小值就行。
时间复杂度 \(O(n^2m)\)
空间复杂度 \(O(nm)\)
代码
#include <bits/stdc++.h>
using namespace std;
string s[57];
int main(){
std::ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t;
cin>>t;
while(t--){
int n,m;
cin>>n>>m;
for(int i = 0;i<n;i++) cin>>s[i];
int ans = ~(1<<31);
for(int i = 0;i<n;i++){
for(int j = i+1;j<n;j++){
int sum = 0;
for(int k = 0;k<m;k++){
sum += abs(s[i][k] - s[j][k]);
}
ans = min(ans,sum);
}
}
cout<<ans<<'\n';
}
return 0;
}
D
题目
https://codeforces.com/problemset/problem/1676/D
题解
思路
知识点:暴力。
暴力枚举最大值,注意边界。
时间复杂度 \(O(n^2m)\)
空间复杂度 \(O(nm)\)
代码
#include <bits/stdc++.h>
using namespace std;
int a[207][207];
int main(){
std::ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t;
cin>>t;
while(t--){
int n,m;
cin>>n>>m;
for(int i = 0;i<n;i++)
for(int j = 0;j<m;j++)
cin>>a[i][j];
int ans = 0;
for(int i = 0;i<n;i++){
for(int j = 0;j<m;j++){
int sum = 0;
for(int k = 0;k<n;k++){
if(0<= j-(i-k) && j-(i-k) <m)sum += a[k][j-(i-k)];
if(0<= j+(i-k) && j+(i-k) <m && j+(i-k) != j-(i-k))sum += a[k][j+(i-k)];
}
ans = max(ans,sum);
}
}
cout<<ans<<'\n';
}
return 0;
}
E
题目
https://codeforces.com/problemset/problem/1676/E
题解
思路
知识点:前缀和,二分查找,贪心。
每次都选最大的即可最少消耗到达目标 \(x\) ,考虑预处理从大到小的前缀和,二分查找第一个大于等于 \(x\) 的和的下标即可。
注意 \(lower\_bound\) 和 \(upper\_bound\) 函数的用法,前者查找大于等于的第一个下标,后者查找大于的第一个下标。并且只可查找“升序”序列,当然这个升序可以自定义,比如用 \(greater\) 把大于定义成升序,即可查找从大到小的序列。
时间复杂度 \(O(nlogn)\)
空间复杂度 \(O(n)\)
代码
#include <bits/stdc++.h>
using namespace std;
int a[150007];
bool cmp(int a,int b){
return a>b;
}
int main(){
std::ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t;
cin>>t;
while(t--){
int n,q;
cin>>n>>q;
for(int i = 1;i<=n;i++) cin>>a[i];
sort(a+1,a+1+n,cmp);
for(int i = 1;i<=n;i++) a[i] += a[i-1];
while(q--){
int x;
cin>>x;
int ans = lower_bound(a+1,a+1+n,x) - a;
cout<<(ans<=n?ans:-1)<<'\n';
}
}
return 0;
}
F
题目
https://codeforces.com/problemset/problem/1676/F
题解
思路
方法1
知识点:贪心,双指针,模拟。
遍历排序后的数组 \(a\) ,记录相同数字个数 \(sum\),如果 \(sum \geq k\) ,则说明这个数字合法,记入临时右值 \(r\) 中,并重置 $sum = 1 $ ,即记录了下一段第一个数字的一次 。
直到某个数字 \(a[i-1]\) 的 \(sum<k\) 或者与后一个数字 \(a[i]\) 差大于 \(1\) ,即 \(a[i] - a[i-1] > 1\) ,说明 \(a[i-1]\) 这个数字在目前段中是最后一个可能合法数字。此时有两种情况,如果 \(sum \geq k\) 则说明数字 \(a[i-1]\) 是合法的更新右值 \(r\) ,否则不合法。之后更新答案,并更新左值为 \(a[i]\) 以及 \(sum = 1\),即新段开始。
遍历结束就可以得到答案。注意初始化方便判断无解。
小细节,如果直接遍历,最后一段合法段可能没法判断,在循环外额外加个判断太丑,可以在末尾加一个不合法的数,循环范围调大一个数字,这样就可以用最后一个不合法数字中断遍历进行判断,而且不合法数字不会参与判断。
时间复杂度 \(O(nlogn)\)
空间复杂度 \(O(n)\)
方法2
知识点:贪心,离散化,双指针,模拟。
用 \(map\) 做数字和次数的映射,可以将区间压缩到数字一个点,再进行遍历即可。思路一样,不合法次数的数字直接跳过,合法数字直接更新右值为这个数字,若这个数字与上一个区间的右值差大于 \(1\) 则更新左值为此数字。每次都更新答案可以少在循环外加一个判断去判断最后一段。
时间复杂度 \(O(nlogn)\)
空间复杂度 \(O(n)\)
两种方法,前者写起来麻烦但常数小,后者写起来方便但常数大容易被卡。
代码
方法1
///直接遍历,非常快
#include <bits/stdc++.h>
using namespace std;
int a[200007];
int main(){
std::ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t;
cin>>t;
while(t--){
int n,k;
cin>>n>>k;
for(int i = 0;i<n;i++){
cin>>a[i];
}
sort(a,a+n);
a[n] = a[n-1] + 2;///小细节,防止最后一段不判断,在后面加个新段就行
int lans = 1,rans = 0,l = a[0],r = 0,sum = 1;
///lans最大区间的左值,rans最大区间的右值,l左值,r右值,sum计数
for(int i = 1;i<=n;i++){///这里需要到n,因为后面有个用来终止的段,不怕越界
if(a[i] == a[i-1]) sum++;
else{
if(sum<k || a[i] - a[i-1] > 1){///此段终止
if(sum>=k) r = a[i-1];///若合法,则更新最大右值
if(rans - lans < r - l) rans = r,lans = l;///更新答案
l = a[i];///更新左值
}
else{///还可以继续增加
r = a[i-1];///更新最大右值
}
sum = 1;///重置计数
}
}
if(!rans) cout<<-1<<'\n';
else cout<<lans<<' '<<rans<<'\n';
}
return 0;
}
方法2
///map,好写但常数大
#include <bits/stdc++.h>
using namespace std;
int main(){
std::ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t;
cin>>t;
while(t--){
map<int,int> cnt;
int n,k;
cin>>n>>k;
for(int i = 0;i<n;i++){
int tmp;
cin>>tmp;
cnt[tmp]++;
}
int lans = 0,rans = -1;///保证r-l的合法也能更新,同时rans能用来判断无解
int l = 0,r = -1;///r保证第一段合法开始l就会被更新,于是l随意
for(auto [i,j]:cnt){///c++17才有这个用法。。。不然老老实实单变量
if(j < k) continue;
if(i - r > 1) l = i;
r = i;
if(rans - lans < r - l){///每次都更新就可以避免最后一段没判断
rans = r;
lans = l;
}
}
if(!~rans) cout<<-1<<'\n';
else cout<<lans<<' '<<rans<<'\n';
}
return 0;
}
G
题目
https://codeforces.com/problemset/problem/1676/G
题解
思路
方法1
知识点:DFS,图论,DP。
用图的方式存树,可以构建一个双向的树,方便从根搜索孩子。
深搜,自上而下搜索子树,自底向上累加子树颜色和,先搜索子树后累加实现。
时间复杂度 \(O(n)\)
空间复杂度 \(O(n^2)\)
方法2
知识点:拓扑排序,图论,DP。
用父亲表示法建树,同时建立节点度的数组。
拓扑排序,自度为0的节点(叶子节点,无子树)开始向上层搜索,进行累加颜色和,一个节点度变为0证明子树颜色和完毕,可以把其放入队列,向其父节点遍历。
时间复杂度 \(O(n)\)
空间复杂度 \(O(n)\)
感觉方法1的常数比方法2小。
代码
方法1
///深搜,自底向上累加子树颜色和,先搜后加实现
#include <bits/stdc++.h>
using namespace std;
int c[4007];
vector<int> g[4007];
void dfs(int u,int fa){
for(int i = 0;i<g[u].size();i++){
if(g[u][i] == fa) continue;///不能以下犯上233
dfs(g[u][i],u);///先把子树的颜色数解决
c[u] += c[g[u][i]];///当前节点的为根的子树颜色数等于自己颜色加所有孩子子树的颜色数
}
}
int main(){
std::ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t;
cin>>t;
while(t--){
int n;
cin>>n;
for(int i = 1;i<=n;i++) g[i].clear(),c[i] = 0;
for(int i = 2;i<=n;i++){
int fa;
cin>>fa;
g[i].push_back(fa);
g[fa].push_back(i);
}
for(int i = 1;i<=n;i++){
char col;
cin>>col;
if(col == 'W') c[i] = 1;
else if(col == 'B') c[i] = -1;///黑色-1,白色1,平衡子树总和为0
}
dfs(1,-1);
int ans = 0;
for(int i = 1;i<=n;i++){
ans += c[i] == 0;
}
cout<<ans<<'\n';
}
return 0;
}
方法2
///拓扑排序,自底向上累加子树颜色和,先度为0(叶子)的节点向上累加实现
#include <bits/stdc++.h>
using namespace std;
int c[4007],deg[4007];
int fa[4007];
void toposort(int n){
queue<int> q;
for(int i = 1;i<=n;i++){
if(!deg[i]) q.push(i);
}
while(!q.empty()){
int cur = q.front();
q.pop();
c[fa[cur]] += c[cur];
deg[fa[cur]]--;
if(!deg[fa[cur]]) q.push(fa[cur]);
}
}
int main(){
std::ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t;
cin>>t;
while(t--){
int n;
cin>>n;
for(int i = 1;i<=n;i++) deg[i] = c[i] = 0;
for(int i = 2;i<=n;i++){
cin>>fa[i];
deg[fa[i]]++;
}
for(int i = 1;i<=n;i++){
char col;
cin>>col;
if(col == 'W') c[i] = 1;
else if(col == 'B') c[i] = -1;///黑色-1,白色1,平衡子树总和为0
}
toposort(n);
int ans = 0;
for(int i = 1;i<=n;i++){
ans += c[i] == 0;
}
cout<<ans<<'\n';
}
return 0;
}
H
题目
https://codeforces.com/problemset/problem/1676/H1
https://codeforces.com/problemset/problem/1676/H2
题解
思路
方法1
知识点:分治,归并排序。
通过肉眼观察法得到最大交点数实际上就是逆序数变种,区别就是等于的也要算,用归并排序改一下即可。
时间复杂度 \(O(nlogn)\)
空间复杂度 \(O(n)\)
方法2
知识点:树状数组。
这块还不会,改天再学,先贴大佬代码。
时间复杂度 \(O(?)\)
空间复杂度 \(O(?)\)
代码
方法1
///归并排序
#include <bits/stdc++.h>
using namespace std;
long long cnt = 0;
int a[200000+7],b[200000+7];
void merge_sort(int l,int r){
if(l >= r) return;///必须>=,因为mid+1可能会大于
int mid = (l+r)/2;
merge_sort(l,mid);
merge_sort(mid+1,r);
int i = l,j = mid+1,k = l;
while(i<=mid && j<=r){
if(a[i]<a[j])///改了这里
b[k++] = a[i++];
else
b[k++] = a[j++],cnt+=mid-i+1;///表示从i到mid的数字都大于a[j]都要算一遍
}
while(i<=mid)
b[k++] = a[i++];
while(j<=r)
b[k++] = a[j++];
memcpy(a+l,b+l,(r-l+1)*sizeof(int));
}
int main(){
std::ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t;
cin>>t;
while(t--){
int n;
cin>>n;
for(int i = 0;i<n;i++)
cin>>a[i];
cnt = 0;
merge_sort(0,n-1);
cout<<cnt<<'\n';
}
return 0;
}
方法2
///树状数组
#include <bits/stdc++.h>
using namespace std;
template <typename T>
struct Fenwick{
const int n;
vector<T> a;
Fenwick(int n):n(n),a(n){}
void add(int x,T v) {
for (int i = x+1;i<=n;i += i&-i){
a[i-1] += v;
}
}
T sum(int x) {
T ans = 0;
for (int i = x;i>0;i -= i&-i){
ans += a[i-1];
}
return ans;
}
T rangeSum(int l,int r){
return sum(r) - sum(l);
}
};
void solve(){
int n;
cin >> n;
vector<int> a(n);
for (int i = 0;i<n;i++) {
cin>>a[i];
a[i]--;
}
Fenwick<int> fen(n);
long long ans = 0;
for (int i = n-1;i>=0;i--) {
ans += fen.sum(a[i]+1);
fen.add(a[i],1);
}
cout<<ans<<"\n";
}
int main(){
std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int t;
cin>>t;
while(t--){
solve();
}
return 0;
}
Codeforces Round #790 (Div. 4) A-H的更多相关文章
- Codeforces Round #371 (Div. 1)
A: 题目大意: 在一个multiset中要求支持3种操作: 1.增加一个数 2.删去一个数 3.给出一个01序列,问multiset中有多少这样的数,把它的十进制表示中的奇数改成1,偶数改成0后和给 ...
- Codeforces Round #160 (Div. 1) 题解【ABCD】
Codeforces Round #160 (Div. 1) A - Maxim and Discounts 题意 给你n个折扣,m个物品,每个折扣都可以使用无限次,每次你使用第i个折扣的时候,你必须 ...
- Codeforces Round #383 (Div. 2) 题解【ABCDE】
Codeforces Round #383 (Div. 2) A. Arpa's hard exam and Mehrdad's naive cheat 题意 求1378^n mod 10 题解 直接 ...
- Codeforces Round #271 (Div. 2)题解【ABCDEF】
Codeforces Round #271 (Div. 2) A - Keyboard 题意 给你一个字符串,问你这个字符串在键盘的位置往左边挪一位,或者往右边挪一位字符,这个字符串是什么样子 题解 ...
- Codeforces Round #177 (Div. 1) 题解【ABCD】
Codeforces Round #177 (Div. 1) A. Polo the Penguin and Strings 题意 让你构造一个长度为n的串,且里面恰好包含k个不同字符,让你构造的字符 ...
- Codeforces Round #182 (Div. 1)题解【ABCD】
Codeforces Round #182 (Div. 1)题解 A题:Yaroslav and Sequence1 题意: 给你\(2*n+1\)个元素,你每次可以进行无数种操作,每次操作必须选择其 ...
- 线段树 Codeforces Round #197 (Div. 2) D. Xenia and Bit Operations
题目传送门 /* 线段树的单点更新:有一个交叉更新,若rank=1,or:rank=0,xor 详细解释:http://www.xuebuyuan.com/1154895.html */ #inclu ...
- Codeforces Round #378 (Div. 2) D题(data structure)解题报告
题目地址 先简单的总结一下这次CF,前两道题非常的水,可是第一题又是因为自己想的不够周到而被Hack了一次(或许也应该感谢这个hack我的人,使我没有最后在赛后测试中WA).做到C题时看到题目情况非常 ...
- Codeforces Round #373 (Div. 2)A B
Codeforces Round #373 (Div. 2) A. Vitya in the Countryside 这回做的好差啊,a想不到被hack的数据,b又没有想到正确的思维 = = [题目链 ...
随机推荐
- Python多线程Threading爬取图片,保存本地,openpyxl批量插入图片到Excel表中
之前用过openpyxl库保存数据到Excel文件写入不了,换用xlsxwriter 批量插入图片到Excel表中 1 import os 2 import requests 3 import re ...
- Docker极简入门:使用Docker-Compose 运行网站浏览量统计Demo
Docker-Compose 是一个可以对 Docker 容器集群的快速编排的工具,能够减轻您心智和手指的负担. 简单的来说 Docker-Compose 就是将你运行多个容器的命令编写到了一起,类似 ...
- 『现学现忘』Git基础 — 14、Git基础操作的总结与补充
目录 1.Git本地版本库结构 2.Git常用操作方法 3.补充:添加多个文件到暂存区 4.补充:提交操作未写备注 5.补充:从工作区直接提交到版本库 1.Git本地版本库结构 如下图所示: 工作区( ...
- Git (常用命令)
某程序猿退休后决定练习书法,于是花重金买下文房四宝.某日,饭后突生雅兴,一番磨墨拟纸 并点上上好檀香.定神片刻,泼墨挥毫,郑重地写下一行:Hello World 斯~ 有被冷到吗哈哈哈 Git常用命令 ...
- 手把手教你在Linux中快速检测端口的 3 个小技巧
一个执着于技术的公众号 前言 无论是要解决网络连接问题还是配置防火墙,第一件事是要检查系统实际打开了哪些端口. 本文介绍了几种快速查找 Linux 系统上哪些端口向外部开放的方法. 什么是开放端口 监 ...
- 老生常谈系列之Aop--JDK动态代理的底层实现原理
老生常谈系列之Aop--JDK动态代理的底层实现原理 前言 在Aop系列里面有两篇文章,分别是老生常谈系列之Aop--Spring Aop原理浅析和老生常谈系列之Aop--Spring Aop源码解析 ...
- 年年出妖事,一例由JSON解析导致的"薛定谔BUG"排查过程记录
前言 做开发这么多年,也碰到无数的bug了.不过再复杂的bug,只要仔细去研读代码,加上debug,总能找到原因. 但是最近公司内碰到的这一个bug,这个bug初看很简单,但是非常妖孽,在一段时间内我 ...
- 安卓导航抽屉 Navigation Drawer 实现沉浸通知栏
在使用 Navigation Drawer Activity 模版的时候,遇到了通知栏无法完全沉浸的问题,尝试搜索一些现有的解决方法,但是或多或少都会存在一些问题,通过反复尝试找到找到了一种比较靠谱的 ...
- Idea之常用插件
效率提升 Jrebel 热部署插件,修改代码编译就生效,节省大量重启服务时间.热部署支持修改方法代码,方法定义,类定义,接口定义(包括swagger文档),修改资源文件,修改mapper.xml(需配 ...
- redis高可用、redis集群、redis缓存优化
今日内容概要 redis高可用 redis集群 redis缓存优化 内容详细 1.redis高可用 # 主从复制存在的问题: 1 主从复制,主节点发生故障,需要做故障转移,可以手动转移:让其中一个sl ...