A. Vasya and Book

简单的取余运用。

#include <iostream>
#include <cstdio>
#include <limits.h>
#include <math.h>
using namespace std;
const int INF = INT_MAX;
int main(){
int T; scanf("%d", &T);
while(T--){
int n, x, y, d;
scanf("%d%d%d%d", &n, &x, &y, &d);
int res = INF; if(abs(x - y) % d == 0) res = min(res, abs(x - y) / d);
if((y - 1) % d == 0) res = min(res, (int)ceil((x - 1.0) / d) + (y - 1) / d);
if((n - y) % d == 0) res = min(res, (int)ceil((double)(n - x) / d) + (n - y) / d);
printf("%d\n", res == INF ? -1 : res);
}
return 0;
}

B. Vova and Trophies

对于每一个\(S\)在的位置,二分出它的最大连续前缀\(lenLeft\)和最大连续后缀\(lenRight\)。

  1. 如果除了这两块前缀以外没有别的\(G\)了,只需把右边的最后一个移到中间来,用\(lenLeft + lenRight\)更新
  2. 否则,可以把别的地方的\(G\)移动过来,用\(lenLeft + lenRight + 1\)更新

对于全字符串都是\(G\)的情况特判即可。

找最大前缀可以用前缀和维护\(sum[i]\) 代表\([1, i]\) 中\(G\)的个数。

总复杂度\(O(nlogn)\),后来发现题解全是\(O(n)\)的,有点自闭了...

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int N = 100010;
int n, sum[N], ans;
char s[N];
int main(){
scanf("%d%s", &n, s + 1);
for(int i = 1; i <= n; i++){
sum[i] = sum[i - 1];
if(s[i] == 'G') sum[i]++;
}
for(int i = 1; i <= n; i++){
if(s[i] == 'S'){
int ansLeft, ansRight;
int lenLeft, lenRight;
//获取左边最长
int l = 0, r = (i - 1);
while(l < r){
int mid = (l + r + 1) >> 1;
int left = (i - 1) - mid + 1;
if(sum[i - 1] - sum[left - 1] == mid) l = mid;
else r = mid - 1;
}
lenLeft = r; ansLeft = (i - 1) - r + 1; //右边最长
l = 0, r = n - (i + 1) + 1;
while(l < r){
int mid = (l + r + 1) >> 1;
int right = (i + 1) + mid - 1;
if(sum[right] - sum[i] == mid) l = mid;
else r = mid - 1;
}
lenRight = r; ansRight = (i + 1) + r - 1; if(sum[ansLeft - 1] || sum[n] - sum[ansRight])
ans = max(ans, lenRight + lenLeft + 1);
else ans = max(ans, lenLeft + lenRight);
} }
if(sum[n] == n) ans = n;
printf("%d\n", ans);
return 0;
}

C. Multi-Subject Competition

正面思考似乎复杂度过高,会达到\(O(nm)\)级别。我们不妨逆向思维,想想每个组对选\(x\)个的贡献。

如果小组的大小$ >= x\(,则可以加入前\)x$大的数(前提 $ > 0\()到\)ans[x]$中。

可以从小到大考虑,在算前\(x\)大的数\(sum\)时先计算前\(x - 1\)大的数的和,这样就可以线性解决了。

时间复杂度\(O(max(m, n))\)

#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
const int N = 100010;
int n, m, s[N], r[N], ans[N], maxn = -1;
vector<int> G[N], sum[N];
int main(){
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++) {
scanf("%d%d", s + i, r + i);
G[s[i]].push_back(r[i]);
}
for(int i = 1; i <= m; i++)
sort(G[i].begin(), G[i].end(), greater<int>() ); for(int i = 1; i <= m; i++){
int sum = 0;
maxn = max(maxn, (int)G[i].size());
for(int j = 0; j < G[i].size(); j++){
sum += G[i][j];
if(sum > 0)ans[j + 1] += sum;
}
}
int res = 0;
for(int i = 1; i <= maxn; i++) res = max(res, ans[i]);
printf("%d", res);
return 0;
}

D. Maximum Diameter Graph

  1. 将满足\(a[i] >= 2\)的点合成一条链。

  2. 如果 \(a[i] = 1\) 的集合中还有数,就分别连向链的头和尾

  3. 如果\(a[i] = 1\)的集合非空,那么将\(i\)点和链上一点满足\(a[x] > 0\)的\(x\)连边,然后把\(a[x]—\),中途如果链的可加入的点不够立即输出\(NO\),然后结束程序。

写程序中想错了一些东西,所以用了优先队列,其实完全不需要…

整个时间复杂度可以达到线性的\(O(n)\)...

#include <iostream>
#include <cstdio>
#include <set>
#include <vector>
#include <queue>
using namespace std;
typedef pair<int, int> PII;
const int N = 510;
int n, a[N], cnt = 0, f[N], head[N], numE = 0;
struct Edge{
int next, from, to;
}e[N * N];
void addEdge(int from, int to){
e[++numE].next = head[from];
e[numE].to = to;
e[numE].from = from;
head[from] = numE;
}
priority_queue<PII> q;
queue<int> list;
int main(){
scanf("%d", &n);
int last = -1, first = 0, res = 0;
for(int i = 1; i <= n; i++){
scanf("%d", a + i);
if(a[i] >= 2) {
if(last != -1) addEdge(i, last), addEdge(last, i), res++;
last = i;
if(!first) first = i;
if(a[i] - 2 > 0) q.push(make_pair(a[i] - 2, i));
}else{
list.push(i);
}
}
if(list.size()){
addEdge(list.front(), first);
addEdge(first, list.front());
list.pop(); res++;
} if(list.size()){
addEdge(list.front(), last);
addEdge(last, list.front());
list.pop(); res++;
} while(!list.empty()){
int u = list.front(); list.pop();
if(q.empty()) { puts("NO"); return 0; }
else{
PII t = q.top(); q.pop();
addEdge(u, t.second);
addEdge(t.second, u);
if(t.first > 1) q.push(make_pair(t.first - 1, t.second));
}
}
printf("YES %d\n%d\n", res, numE >> 1);
for(int i = 1; i <= numE; i += 2){
printf("%d %d\n", e[i].from, e[i].to);
}
return 0;
}

E. Increasing Frequency

…太难啦…

设\(sum[x][i]\)为\([1, i]\)区间内\(x\)数字出现次数。

我可以在\([l, r]\)区间内把数\(x\)都加上\(c - x\),但是在\([l, r]\)中原本是\(c\)的就没有了

修改后全序列\(c\)数次数的变化量,代表相对于之前\(c\)数存在的个数,到答案我增加了多少。

\(ans[x]\) 表示把数字\(x\)变成\(c\)的最大的变化量(也就是选择不同\([l, r]\)造成的最大的变化量)

可以写成:

\(ans[x] = max\{sum[x][r] - sum[x][l - 1] - (sum[c][r] - sum[c][l - 1])\} (1 <= l <= r <= n)\)

我们可以枚举\(r\)的位置,找到一个\(l\)使其最小。

这个式子可以转变为:

\(ans[x] = max\{sum[x][r] - sum[c][r] - (sum[x][l - 1] - sum[c][l - 1])\} (1 <= l <= r <= n)\)

由于\(l <= r\) 我们可以考虑在枚举\(r\)的位置的同时维护一个最小值。

设\(min[x][i]\) 表示\([1, i]\) 这段的\(min\{sum[x][j] - sum[c][j]\} (1 <= j <= i)\)。

那么变化量就可以写成:

\(ans[x] = max\{sum[x][r] - sum[c][r] - min[x][r]\}\)(1 <= r <= n)

我们发现可以滚动掉\(sum\)数组与\(min\)数组的第二维度…于是,空间和时间的问题都完美解决啦...

#include <cstdio>
#include <iostream>
#include <cmath>
using namespace std;
const int N = 500010;
int n, c, a[N], ans[N], sum[N], minn[N];
int main(){
scanf("%d%d", &n, &c);
for(int i = 1; i <= n; i++) scanf("%d", a + i);
for(int i = 1; i <= n; i++){
minn[a[i]] = min(minn[a[i]], sum[a[i]] - sum[c]);
sum[a[i]]++;
ans[i] = max(ans[i], sum[a[i]] - sum[c] - minn[a[i]]);
}
int res = sum[c];
for(int i = 1; i <= n; i++)
res = max(res, sum[c] + ans[i]);
printf("%d", res);
return 0;
}

Codeforces Edu Round 55 A-E的更多相关文章

  1. Codeforces Beta Round #55 (Div. 2)

    Codeforces Beta Round #55 (Div. 2) http://codeforces.com/contest/59 A #include<bits/stdc++.h> ...

  2. Codeforces Beta Round #80 (Div. 2 Only)【ABCD】

    Codeforces Beta Round #80 (Div. 2 Only) A Blackjack1 题意 一共52张扑克,A代表1或者11,2-10表示自己的数字,其他都表示10 现在你已经有一 ...

  3. Codeforces Beta Round #62 题解【ABCD】

    Codeforces Beta Round #62 A Irrational problem 题意 f(x) = x mod p1 mod p2 mod p3 mod p4 问你[a,b]中有多少个数 ...

  4. Codeforces Beta Round #83 (Div. 1 Only)题解【ABCD】

    Codeforces Beta Round #83 (Div. 1 Only) A. Dorm Water Supply 题意 给你一个n点m边的图,保证每个点的入度和出度最多为1 如果这个点入度为0 ...

  5. Codeforces Beta Round #13 C. Sequence (DP)

    题目大意 给一个数列,长度不超过 5000,每次可以将其中的一个数加 1 或者减 1,问,最少需要多少次操作,才能使得这个数列单调不降 数列中每个数为 -109-109 中的一个数 做法分析 先这样考 ...

  6. Codeforces Beta Round #51 C. Pie or die 博弈论找规律 有趣的题~

    C. Pie or die Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/55/problem/ ...

  7. Codeforces Beta Round #51 B. Smallest number dfs

    B. Smallest number Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/55/pro ...

  8. Codeforces Beta Round #51 A. Flea travel 水题

    A. Flea travel Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/55/problem ...

  9. Codeforces Beta Round #51 D. Beautiful numbers 数位dp

    D. Beautiful numbers Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/55/p ...

随机推荐

  1. IP 层收发报文简要剖析6--ip_forward 报文转发

    //在函数ip_route_input_slow->ip_mkroute_input注册, /* * IP数据包的转发是由ip_forward()处理,该函数在ip_rcv_finish() * ...

  2. Spring源码之Springboot中监听器介绍

    https://www.bilibili.com/video/BV12C4y1s7dR?p=11 监听器模式要素 事件 监听器 广播器 触发机制 Springboot中监听模式总结 在SpringAp ...

  3. Docker版EKL安装记录文档

    Docker版EKL安装记录文档 拉取已下三个镜像 docker.io/logstash 7.5.2 b6518c95ed2f 6 months ago 805 MB docker.io/kibana ...

  4. 算法:线性时间选择(C/C++)

    Description 给定线性序集中n个元素和一个整数k,n<=2000000,1<=k<=n,要求找出这n个元素中第k小的数. Input 第一行有两个正整数n,k. 接下来是n ...

  5. Java编译程序和运行过程详解

    java整个编译以及运行的过程相当繁琐,我就举一个简单的例子说明: 编译原理简单过程:词法分析 --> 语法分析 --> 语义分析和中间代码生成 --> 优化 --> 目标代码 ...

  6. 状态模式(Established close)

    状态模式(Established close) 引子 铁扇公主:以前陪我看月亮的时候,叫人家小甜甜,现在新人胜旧人了,叫人家牛夫人! 定义 Allow an object to alter its b ...

  7. 精尽 MyBatis 源码分析 - 基础支持层

    该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...

  8. RSA脚本环境配置-攻防世界-OldDriver

    [Crypto] 题目链接 [RSA算法解密] 审题分析 首先拿到一个压缩包,解压得到文件enc.txt. 先不用去管其他,第一眼enc马上联想到 RSA解密.接着往下看 [{"c" ...

  9. IDEA创建WebService服务端与客户端

    创建服务端 一.file–>new–>project 二.点击next后输入服务端名,点击finish,生成目录如下 三.在 HelloWorld.Java 文件中右击,选 Tools 的 ...

  10. prometheus监控实战--基础

    1.简介 prometheus就是监控系统+TSDB(时间序列数据库),通过pull方式从exporter获取时间序列数据,存入本地TSDB,被监控端需安装exporter作为http端点暴露指标数据 ...