Codeforces Round #776 (Div
Codeforces Round #776 (Div. 3)
CodeForces - 1650D Twist the Permutation
给定你数组a:1 2 3 ... n,一共有n次操作,每次操作可以把\(a_i\)移到最左边,然后对\(i+1\)位以后不会产生影响,每次操作可以进行任意次,例如 :5 4 3 1 2 ,现在处于第三次操作,那么我只能在\(a_3\)位置上操作,操作一次后:
3 5 4 1 2,操作两次后:4 3 5 1 2,以此类推,现在给你操作完之后的数组a,让你计算出他在每个位置上的操作数分别是多少?
题解:思维+模拟
我们可以倒过来想,因为每一次操作不会对他后面的数造成影响,所以元素n现在的位置一定是最后一次操作操作若干次得到的,那么我们就得到了最后一次的操作数,根据这个操作数我们进行还原,还原得到的数组中n-1的位置一定是倒数第二次操作得到的,这样我们就得到了倒数第二次的操作数....以此类推
#include <bits/stdc++.h>
#define Zeoy std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0)
#define debug(x) cerr << #x << '=' << x << endl
#define all(x) (x).begin(), (x).end()
#define rson id << 1 | 1
#define lson id << 1
#define int long long
#define mpk make_pair
#define endl '\n'
using namespace std;
typedef unsigned long long ULL;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-9;
const int N = 2e5 + 10, M = 4e5 + 10;
int n, a[N], b[N];
int ans[N];
void solve()
{
cin >> n;
for (int i = 1; i <= n; ++i)
cin >> a[i];
for (int i = n; i >= 1; --i)
{
int step = -1;
if (i != n)
{
for (int j = 1; j <= n; ++j)
a[j] = b[j];
}
for (int j = 1; j <= i; ++j)
if (a[j] == i)
{
if (j != i)
step = j;
else
step = 0;
break;
}
if (step == -1)
{
cout << -1 << endl;
return;
}
ans[i] = step;
for (int j = 1; j <= i; ++j)
{
int pos = (j - step + i) % i;
if (pos == 0)
pos += i;
b[pos] = a[j];
}
b[i] = i;
}
for (int i = 1; i <= n; ++i)
cout << ans[i] << " ";
cout << endl;
}
signed main(void)
{
Zeoy;
int T = 1;
cin >> T;
while (T--)
{
solve();
}
return 0;
}
CodeForces - 1650E Rescheduling the Exam
给你一张1-d长度的时间表,在这个时间表内安排了n场考试,你现在只能任意改变一场考试的时间,使得两场考试之间的休息时间u的最小值最大
题解:贪心+模拟
其实二分答案也能做,但是太难调了,直接放弃了,我们发现如果要使u变大,我们需要改变休息时间最短的两场考试\(a_i,a_{i-1}\)其中之一,那么假设我们改变\(a_i\)的时间,那么它可以插入的地方只有两个地方才有可能使得答案变大:
- 休息时间最长的两场考试中间,那么插入后他们之间的休息时间为:\((a_j-a_{j-1}-2)/2\)
- 插在最后一天\(d\)处,休息时间为:\(d-a[last]-1\),注意\(a[last]\)是会改变的
那么我们贪心在这两种插入中我们选择最大值,然后最大值再和改变后休息时间最短\(minn\)取\(min\)即可
那么我们已经考虑了改变\(a_i\)的情况,对于\(a_{i-1}\)只要\(i>1\)我们都可以按照上面的流程再走一遍,看一下u会不会更大
#include <bits/stdc++.h>
#define Zeoy std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0)
#define debug(x) cerr << #x << '=' << x << endl
#define all(x) (x).begin(), (x).end()
#define rson id << 1 | 1
#define lson id << 1
#define int long long
#define mpk make_pair
#define endl '\n'
using namespace std;
typedef unsigned long long ULL;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-9;
const int N = 2e5 + 10, M = 4e5 + 10;
int n, d;
int a[N];
int cal(int pos)
{
int pre = 0;
int minn = INF, maxx = -INF;
for (int i = 1; i <= n; ++i)
{
if (i != pos)
{
minn = min(minn, a[i] - a[pre] - 1);
maxx = max(maxx, a[i] - a[pre] - 1);
pre = i;
}
}
return min(minn, max((maxx - 1) / 2, d - a[pre] - 1));
}
void solve()
{
cin >> n >> d;
for (int i = 1; i <= n; ++i)
cin >> a[i];
int minn = INF;
int pos = -1;
for (int i = 1; i <= n; ++i)
if (a[i] - a[i - 1] - 1 < minn)
{
pos = i;
minn = a[i] - a[i - 1] - 1;
}
int ans = -INF;
ans = max(ans, cal(pos));
if (pos > 1)
ans = max(ans, cal(pos - 1));
cout << ans << endl;
}
signed main(void)
{
Zeoy;
int T = 1;
cin >> T;
while (T--)
{
solve();
}
return 0;
}
CodeForces - 1650F Vitaly and Advanced Useless Algorithms
现在给你n个任务,每个任务都有截止时间,你需要将每个任务进程都完成100%,才算成功,又给定m种操作,每次操作给定\(e,t,p\),代表对于任务e,可以利用t时间将其进度增加p,每种操作只能用一次,求最后能否完成所有任务,如果能完成求出完成所有任务的最短用时,并将选择的操作以任意顺序输出
题解:01背包求方案数,感觉是一道好题目,下次记得复习
首先这是一个先明显的01背包求方案数的题目,因为存在截止时间,所以我们肯定要从截止时间短的任务开始做起,我们只需要对于每一个任务所对应的操作进行01背包,然后如果该任务完成的最短时间超过其给定的时间,那么说明后面的任务都完成不了了,如果能完成,那么剩余的时间我们可以分配给下一个任务,那么对于每次任务我们在dp时再记录方案即可
对于这道题,两个重点我们需要把握:
- 如何在一维滚动数组中记录方案数,我们可以开个vector[N],对于每次转移我们先将方案数转移,然后再在vector[]后面加上本次操作的id,\(pre[j] = pre[max(0ll, j - p)],\ \ \ \ pre[j].push\_back(id);\)
- 如何对所有操作数按照任务分类,同样可以利用vecrot,借助邻接表的思想进行分类
#include <bits/stdc++.h>
#define Zeoy std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0)
#define debug(x) cerr << #x << '=' << x << endl
#define all(x) (x).begin(), (x).end()
#define rson id << 1 | 1
#define lson id << 1
#define int long long
#define mpk make_pair
#define endl '\n'
using namespace std;
typedef unsigned long long ULL;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-9;
const int N = 1e5 + 10, M = 4e5 + 10;
int n, m;
vector<array<int, 3>> v[N];
int a[N], f[N];
int dif[N];
vector<int> ans;
void solve()
{
ans.clear();
cin >> n >> m;
for (int i = 1; i <= n; ++i)
cin >> a[i];
for (int i = 1; i <= n; ++i)
dif[i] = a[i] - a[i - 1];
for (int i = 1; i <= n; ++i)
v[i].clear();
for (int i = 1, e, t, p; i <= m; ++i)
{
cin >> e >> t >> p;
v[e].push_back({t, p, i});
}
for (int i = 1; i <= n; ++i)
{
vector<int> pre[101];
f[0] = 0;
for (int j = 1; j <= 105; ++j)
f[j] = INF;
for (auto &[t, p, id] : v[i])
{
for (int j = 100; j >= 0; --j)
{
if (f[j] > f[max(0ll, j - p)] + t)
{
f[j] = f[max(0ll, j - p)] + t;
pre[j] = pre[max(0ll, j - p)];
pre[j].push_back(id);
}
}
}
if (f[100] > dif[i])
{
cout << -1 << endl;
return;
}
dif[i + 1] += dif[i] - f[100];
for (auto id : pre[100])
ans.push_back(id);
}
cout << ans.size() << endl;
for (auto id : ans)
cout << id << " ";
cout << endl;
}
signed main(void)
{
Zeoy;
int T = 1;
cin >> T;
while (T--)
{
solve();
}
return 0;
}
CodeForces - 1650G Counting Shortcuts
给定一个无向图,没有自环和重边,给定起点st和终点ed,假设st到ed的最短距离为x,让你求出所有st到ed路径长度<=x+1的所有路径数(可以是简单路径,也可以不是简单路径)
题解:次短路和最短路求方案数 + 计数DP: 需要回顾复习
这是一道经典的最短路求方案数的问题,但同时我们只要再记录次短路的长度和方案数即可,我们可以在\(dijktra\)中对方案数进行记录和转移
现在解释一下\(dis[u][0/1]\):表示起点到u节点的最短距离(0)和次短距离(1)
同时我们在跑dij的时候将路径入队的同时需要分清楚这条路径是最短路还是次短路,我们可以定义结构体,在结构体中增加一个\(flag\)用来区分最短路和次短路
我们先来解释一下dp计数部分:
状态表示:\(f[u][0/1]\):代表从起点到u节点最短路径(0)的方案数,次短路(1)的方案数
状态属性:数量
状态转移:我们考虑四种情况
- \(dis[u][type]+w\)小于最短路\(dis[v][0]\),如果最短路已经被松弛过了,我们可以将其方案数和距离转移给次短距离,并将次短路入队,然后再将\(f[u][type]\)转移给最短路后入队;如果没有被松弛过,直接将\(f[u][type]\)转移给最短路后入队
- \(dis[u][type]+w\)等于最短路\(dis[v][0]\),该点最短路的方案数需要增加\(f[v][0] += f[u][type]\)
- \(dis[u][type]+w\)大于次短路\(dis[v][1]\),修改次短路后,对方案数进行转移\(f[v][1] = f[u][type]\),然后入队
- \(dis[u][type]+w\)等于次短路\(dis[v][1]\),该点次短路的方案需要增加\(f[v][1] += f[u][type]\)
那么对于答案输出部分:
如果\(f[ed][1]-f[ed][0]==1\),说明满足题目条件,答案为\(f[ed][0]+f[ed][1]\)
如果\(f[ed][1]-f[ed][0]!=1\), 不满足题目条件,答案为\(f[ed][0]\)
#include <bits/stdc++.h>
#define Zeoy std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0)
#define debug(x) cerr << #x << '=' << x << endl
#define all(x) (x).begin(), (x).end()
#define rson id << 1 | 1
#define lson id << 1
#define int long long
#define mpk make_pair
#define endl '\n'
using namespace std;
typedef unsigned long long ULL;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-9;
const int N = 2e5 + 10, M = 4e5 + 10;
int n, m;
vector<pii> g[N];
int st, ed;
int f[N][2], dis[N][2], vis[N][2];
struct node
{
int u, dis, flag;
bool operator<(const node &t) const
{
return dis > t.dis;
}
};
void dij(int st)
{
for (int i = 1; i <= n; ++i)
{
dis[i][0] = dis[i][1] = inf;
f[i][0] = f[i][1] = 0;
vis[i][0] = vis[i][1] = 0;
}
priority_queue<node> q;
q.push({st, 0, 0});
dis[st][0] = 0;
f[st][0] = 1;
while (q.size())
{
node t = q.top();
int u = t.u, type = t.flag;
q.pop();
if (vis[u][type])
continue;
vis[u][type] = 1;
for (auto &[v, w] : g[u])
{
if (dis[v][0] > dis[u][type] + w)
{
if (dis[v][0] != inf)
{
f[v][1] = f[v][0];
dis[v][1] = dis[v][0];
q.push({v, dis[v][1], 1});
}
f[v][0] = f[u][type];
dis[v][0] = dis[u][type] + w;
q.push({v, dis[v][0], 0});
}
else if (dis[v][0] == dis[u][type] + w)
f[v][0] = (f[v][0] + f[u][type]) % mod;
else if (dis[v][1] > dis[u][type] + w)
{
f[v][1] = f[u][type];
dis[v][1] = dis[u][type] + w;
q.push({v, dis[v][1], 1});
}
else if (dis[v][1] == dis[u][type] + w)
f[v][1] = (f[v][1] + f[u][type]) % mod;
}
}
}
void solve()
{
cin >> n >> m;
cin >> st >> ed;
for (int i = 1; i <= n; ++i)
g[i].clear();
for (int i = 1, u, v; i <= m; ++i)
{
cin >> u >> v;
g[u].push_back({v, 1});
g[v].push_back({u, 1});
}
dij(st);
if (dis[ed][1] - dis[ed][0] == 1)
cout << (f[ed][0] + f[ed][1]) % mod << endl;
else
cout << f[ed][0] << endl;
}
signed main(void)
{
Zeoy;
int T = 1;
cin >> T;
while (T--)
{
solve();
}
return 0;
}
Codeforces Round #776 (Div的更多相关文章
- Codeforces Round #366 (Div. 2) ABC
Codeforces Round #366 (Div. 2) A I hate that I love that I hate it水题 #I hate that I love that I hate ...
- Codeforces Round #354 (Div. 2) ABCD
Codeforces Round #354 (Div. 2) Problems # Name A Nicholas and Permutation standard input/out ...
- Codeforces Round #368 (Div. 2)
直达–>Codeforces Round #368 (Div. 2) A Brain’s Photos 给你一个NxM的矩阵,一个字母代表一种颜色,如果有”C”,”M”,”Y”三种中任意一种就输 ...
- cf之路,1,Codeforces Round #345 (Div. 2)
cf之路,1,Codeforces Round #345 (Div. 2) ps:昨天第一次参加cf比赛,比赛之前为了熟悉下cf比赛题目的难度.所以做了round#345连试试水的深浅..... ...
- Codeforces Round #279 (Div. 2) ABCDE
Codeforces Round #279 (Div. 2) 做得我都变绿了! Problems # Name A Team Olympiad standard input/outpu ...
- Codeforces Round #262 (Div. 2) 1003
Codeforces Round #262 (Div. 2) 1003 C. Present time limit per test 2 seconds memory limit per test 2 ...
- Codeforces Round #262 (Div. 2) 1004
Codeforces Round #262 (Div. 2) 1004 D. Little Victor and Set time limit per test 1 second memory lim ...
- Codeforces Round #371 (Div. 1)
A: 题目大意: 在一个multiset中要求支持3种操作: 1.增加一个数 2.删去一个数 3.给出一个01序列,问multiset中有多少这样的数,把它的十进制表示中的奇数改成1,偶数改成0后和给 ...
- Codeforces Round #268 (Div. 2) ABCD
CF469 Codeforces Round #268 (Div. 2) http://codeforces.com/contest/469 开学了,时间少,水题就不写题解了,不水的题也不写这么详细了 ...
- 贪心+模拟 Codeforces Round #288 (Div. 2) C. Anya and Ghosts
题目传送门 /* 贪心 + 模拟:首先,如果蜡烛的燃烧时间小于最少需要点燃的蜡烛数一定是-1(蜡烛是1秒点一支), num[g[i]]记录每个鬼访问时已点燃的蜡烛数,若不够,tmp为还需要的蜡烛数, ...
随机推荐
- C++_虚函数
1.目的: 派生类继承自基类.使用指针或引用访问派生类对象时,指针或引用本身所指向的类型可以是基类而不是派生类.如果派生类覆盖了基类中的方法,通过上述指针或引用调用该方法时,可以有两种结果: 调用到基 ...
- SpringMVC的表单组件、国际化
spring mvc 的表单标签库 1.Student实体类 package com.southwind.POJO; import lombok.Data; @Data public class St ...
- 微信小程序数字转中文wxs
场景: 传入数字,转换成天数,比如:index = 1 转换后则为 一,在页面中的应用就是<view>第{{index}}天</view>,转为第几天. <view> ...
- mac os黑苹果安装
前言 习惯了mac敲代码的攻城师很难再去适应windows,那么如何在windows上安装苹果系统呢?用黑苹果. 关于黑苹果的安装,网上的一大堆教程显得过于啰嗦,又是安装Unlocker破解mac限制 ...
- CF750H New Year and Snowy Grid
\(\text{Solution}\) 这个问题是不好判断的 考虑简单点的,\((1,1)\) 到 \((h,w)\) 是否连通 那么只要在最外围一圈 #(显然一些位置不能加),判断 \((h+1,n ...
- JZOJ 6904. 【2020.11.28提高组模拟】T3 树上询问(query)
题目 你有一棵 \(n\) 节点的树 ,回答 \(m\) 个询问,每次询问给你两个整数 \(l,r\) ,问存在多少个整数 \(k\) 使得从 \(l\) 沿着 \(l \to r\) 的简单路径走 ...
- 我在京东做研发 | 从好玩到好用,爆火ChatGPT前沿分享
| 嘉宾:吴友政,京东集团高级总监.京东科技语音语言算法部负责人. 2006年中科院自博士毕业后,先后在日本国立信息通信研究机构.英国爱丁堡大学.索尼中国研究院从事自然语言处理相关研究工作,主要聚焦自 ...
- Vulnhub:Five86-2靶机
kali:192.168.111.111 靶机:192.168.111.211 信息收集 端口扫描 nmap -A -v -sV -T5 -p- --script=http-enum 192.168. ...
- QtQuick与Qml介绍
文章纲要: 1.QtQuick是什么 2.qml与QtQuick关系 一.QtQuick是什么 "quick--快速创建应用程序" "quick--Qt User Int ...
- 2.13python基础知识
编程语言的发展史 1.机器语言:内部用0和1表示 2.汇编语言:简单的字母表示二进制 3.高级语言:人类可以理解的 1.执行效率:机器语言>汇编语言>高级语言(编译型>解释型) 2. ...