SCOI 2015 Day1 简要题解
「SCOI2015」小凸玩矩阵
题意
一个 \(N \times M\)( $ N \leq M $ )的矩阵 $ A $,要求小凸从其中选出 $ N $ 个数,其中任意两个数字不能在同一行或同一列,现小凸想知道选出来的 $ N $ 个数中第 $ K $ 大的数字的最小值是多少。
$ 1 \leq K \leq N \leq M \leq 250, 1 \leq A_{i, j} \leq 10 ^ 9 $
题解
一道简单的网络流题。
不难发现第 \(K\) 大和第 \(N - K + 1\) 小是本质一样的。
所以就是要使得第 \(N - K + 1\) 小尽量小,那么我们二分这个最小值 \(min\) 就行了。
然后我们对于 \(A_{i, j} \le min\) 的点 \((i, j)\) 考虑,如果能从中选出至少 \(N - K + 1\) 个点就是合法的。
然后直接上二分图建模就行了。
用 Hungray 可以跑过去 ,但是更喜欢 Dinic 的复杂度。
所以最后复杂度就是 \(O(N^2 \log A)\) 的,轻松通过,甚至能跑更大范围。
代码
#include <bits/stdc++.h>
#define For(i, l, r) for(register int i = (l), i##end = (int)(r); i <= i##end; ++i)
#define Fordown(i, r, l) for(register int i = (r), i##end = (int)(l); i >= i##end; --i)
#define Set(a, v) memset(a, v, sizeof(a))
#define Cpy(a, b) memcpy(a, b, sizeof(a))
#define debug(x) cout << #x << ": " << (x) << endl
#define DEBUG(...) fprintf(stderr, __VA_ARGS__)
using namespace std;
template<typename T> inline bool chkmin(T &a, T b) { return b < a ? a = b, 1 : 0; }
template<typename T> inline bool chkmax(T &a, T b) { return b > a ? a = b, 1 : 0; }
inline int read() {
int x(0), sgn(1); char ch(getchar());
for (; !isdigit(ch); ch = getchar()) if (ch == '-') sgn = -1;
for (; isdigit(ch); ch = getchar()) x = (x * 10) + (ch ^ 48);
return x * sgn;
}
void File() {
#ifdef zjp_shadow
freopen ("2006.in", "r", stdin);
freopen ("2006.out", "w", stdout);
#endif
}
const int N = 255, inf = 0x3f3f3f3f;
int n, m, k, a[N][N];
template<int Maxn, int Maxm>
struct Dinic {
int Head[Maxn], Next[Maxm], to[Maxm], cap[Maxm], e;
void Init() {
Set(Head, 0); e = 1;
}
inline void add_edge(int u, int v, int flow) {
to[++ e] = v; Next[e] = Head[u]; cap[e] = flow; Head[u] = e;
}
inline void Add(int u, int v, int flow) {
add_edge(u, v, flow); add_edge(v, u, 0);
}
int S, T, dis[Maxn];
bool Bfs() {
queue<int> Q; Q.push(S); Set(dis, 0); dis[S] = 1;
while (!Q.empty()) {
int u = Q.front(); Q.pop();
for (int i = Head[u], v = to[i]; i; v = to[i = Next[i]])
if (cap[i] && !dis[v]) dis[v] = dis[u] + 1, Q.push(v);
}
return dis[T];
}
int cur[Maxn];
int Dfs(int u, int flow) {
if (!flow || u == T) return flow;
int res = 0, f;
for (int& i = cur[u], v = to[i]; i; v = to[i = Next[i]])
if (dis[v] == dis[u] + 1 && (f = Dfs(v, min(flow, cap[i])))) {
res += f; cap[i] -= f; cap[i ^ 1] += f;
if (!(flow -= f)) break ;
}
return res;
}
inline int Run() {
int res = 0;
while (Bfs())
Cpy(cur, Head), res += Dfs(S, inf);
return res;
}
};
Dinic<N * 2, N * N * 2> T;
bool Check(int lim) {
T.Init();
T.S = n + m + 1, T.T = n + m + 2;
For (i, 1, n) For (j, 1, m)
if (a[i][j] <= lim) T.Add(i, j + n, 1);
For (i, 1, n) T.Add(T.S, i, 1);
For (i, 1, m) T.Add(i + n, T.T, 1);
return T.Run() >= k;
}
int main () {
File();
n = read(); m = read(); k = n - read() + 1;
int l = inf, r = -inf;
For (i, 1, n) For (j, 1, m)
a[i][j] = read(), chkmin(l, a[i][j]), chkmax(r, a[i][j]);
int ans = 0;
while (l <= r) {
int mid = (l + r) >> 1;
if (Check(mid)) ans = mid, r = mid - 1;
else l = mid + 1;
}
printf ("%d\n", ans);
return 0;
}
「SCOI2015」国旗计划
题意
给你一个长为 \(M\) 的环,共有 \(N\) 个互不包含的环上区间 \([C_i, D_i]\) (当 \(C_i > D_i\) 的时候相当于 \([C_i, M]\) 和 \([1, D_i]\) 拼成的一个区间)。
每次强制选择第 \(i\) 个区间,询问至少还要选择多少个区间才能满足所有点都被覆盖。
$ N \leq 2 \times 10 ^ 5, M < 10 ^ 9, 1 \leq C_i, D_i \leq M $
题解
如果是序列上,那么就是很简单的一道倍增题了。
只需要处理一下每个点被跨过的区间 \([l_i, r_i]\) 的最大的 \(r_i\) 就行了,因为每次都向尽量走的远。
然后预处理第 \(i\) 号点走 \(2^j\) 步能到达的最远点 \(to_{i, j}\) 就行了。每次查询直接倍增就行了。
环上的麻烦一点,首先倍长拆环。然后你有可能你会绕环走了好几圈,这个你就多记下一个走了 \(2^j\) 步走了的距离 \(dis_{i, j}\) 就行了。(因为这样比较好写)
每次要走的距离分类讨论就行了。
然后最后的复杂度就是 \(O(N \log N)\) 的,轻松通过。
其实可以把这个倍增结构放到树上,每次就只需要查 \(dis\) 的差就行了(如果不在子树内要 \(+1\) ),复杂度可以优化成 \(O(N)\) 的。
代码
#include <bits/stdc++.h>
#define For(i, l, r) for(register int i = (l), i##end = (int)(r); i <= i##end; ++i)
#define Fordown(i, r, l) for(register int i = (r), i##end = (int)(l); i >= i##end; --i)
#define Set(a, v) memset(a, v, sizeof(a))
#define Cpy(a, b) memcpy(a, b, sizeof(a))
#define debug(x) cout << #x << ": " << (x) << endl
#define DEBUG(...) fprintf(stderr, __VA_ARGS__)
#define pb push_back
using namespace std;
typedef long long ll;
template<typename T> inline bool chkmin(T &a, T b) { return b < a ? a = b, 1 : 0; }
template<typename T> inline bool chkmax(T &a, T b) { return b > a ? a = b, 1 : 0; }
inline int read() {
int x(0), sgn(1); char ch(getchar());
for (; !isdigit(ch); ch = getchar()) if (ch == '-') sgn = -1;
for (; isdigit(ch); ch = getchar()) x = (x * 10) + (ch ^ 48);
return x * sgn;
}
void File() {
#ifdef zjp_shadow
freopen ("2007.in", "r", stdin);
freopen ("2007.out", "w", stdout);
#endif
}
const int N = 4e5 + 1e3;
ll dis[N * 2][21];
int to[N * 2][21], l[N], r[N];
vector<int> V[N * 2];
int n, m, Hash[N * 2], len;
inline int Get_Id(int x) {
return lower_bound(Hash + 1, Hash + len + 1, x) - Hash;
}
int main () {
File();
n = read(); m = read();
For (i, 1, n) {
Hash[++ len] = l[i] = read();
Hash[++ len] = r[i] = read();
}
sort(Hash + 1, Hash + len + 1);
len = unique(Hash + 1, Hash + len + 1) - Hash - 1;
For (i, 1, n) {
l[i] = Get_Id(l[i]), r[i] = Get_Id(r[i]);
if (l[i] > r[i]) V[1].pb(r[i]), V[l[i]].pb(r[i] + len);
else V[l[i]].pb(r[i]);
}
int cur = 0;
For (i, 1, len) {
for (int v : V[i]) chkmax(cur, v);
dis[i][0] = dis[i + len][0] = cur - i;
to[i][0] = to[i + len][0] = cur;
}
int Lim = ceil(log2(len << 1));
For (j, 1, Lim) For (i, 1, len << 1) {
to[i][j] = to[to[i][j - 1]][j - 1];
dis[i][j] = dis[i][j - 1] + dis[to[i][j - 1]][j - 1];
}
For (i, 1, n) {
int ans = 0, u = r[i], need = l[i] <= r[i] ? len - (r[i] - l[i]) : l[i] - r[i];
Fordown (j, Lim, 0)
if (dis[u][j] < need)
need -= dis[u][j], u = to[u][j], ans |= 1 << j;
printf ("%d%c", ans + 2, i == iend ? '\n' : ' ');
}
return 0;
}
SCOI 2015 Day1 简要题解的更多相关文章
- SCOI 2015 Day2 简要题解
「SCOI2015」小凸玩密室 题意 小凸和小方相约玩密室逃脱,这个密室是一棵有 $ n $ 个节点的完全二叉树,每个节点有一个灯泡.点亮所有灯泡即可逃出密室.每个灯泡有个权值 $ A_i $,每条边 ...
- A · F · O —— JLOI2018翻车记(附Day1简要题解)
JLOI2018翻车记 并不知道该怎么写... 算了还是按照标准剧情来吧 这应该是一篇写得非常差的流水账... 2018.04.04 Day -1 省选前在机房的最后一天. 压力并不是很大,毕竟联赛 ...
- JLOI2015 DAY1 简要题解
「JLOI2015」有意义的字符串 题意 给你 \(b, d, n\) 求 \[ [(\frac{b + \sqrt d}2)^n] \mod 7528443412579576937 \] \(0 & ...
- SCOI2016 Day1 简要题解
目录 「SCOI2016」背单词 题意 题解 代码 「SCOI2016」幸运数字 题意 题解 总结 代码 「SCOI2016」萌萌哒 题意 题解 总结 代码 「SCOI2016」背单词 题意 这出题人 ...
- [NOIP 2018 Day1] 简要题解
[题目链接] 铺设道路 : https://www.luogu.org/problemnew/show/P5019 货币系统 : https://www.luogu.org/problemnew/sh ...
- AHOI2013 Round2 Day1 简要题解
第一题,好吧这是个dp.(搜素也能在BZOJ上卡过). 第二题,BFS搜索碰到的立方体面数,智硬没有想到... 第三题,其实一看就有思路,但关键是求x坐标不交的矩形对数+y坐标不交的矩形对数 - x, ...
- Noip 2014酱油记+简要题解
好吧,day2T1把d默认为1也是醉了,现在只能期待数据弱然后怒卡一等线吧QAQ Day0 第一次下午出发啊真是不错,才2小时左右就到了233,在车上把sao和fate补掉就到了= = 然后到宾馆之后 ...
- Tsinghua 2018 DSA PA2简要题解
反正没时间写,先把简要题解(嘴巴A题)都给他写了记录一下. upd:任务倒是完成了,我也自闭了. CST2018 2-1 Meteorites: 乘法版的石子合并,堆 + 高精度. 写起来有点烦貌似. ...
- Codeforces 863 简要题解
文章目录 A题 B题 C题 D题 E题 F题 G题 传送门 简要题解?因为最后一题太毒不想写了所以其实是部分题解... A题 传送门 题意简述:给你一个数,问你能不能通过加前导000使其成为一个回文数 ...
随机推荐
- 广州商学院16级软工一班&二班-第一次作业成绩
广州商学院16级软工一班&二班-第一次作业成绩 作业地址 16软工一班 16软工二班 总结 本次作业反映了几个比较严重的问题: 不按要求阅读相应的文章,回答问题只是敷衍几句. 部分同学的版式混 ...
- Echarts x轴文本内容太长的几种解决方案
Echarts 标签中文本内容太长的时候怎么办 ? - 1对文本进行倾斜 在xAxis.axisLabe中修改rotate的值 xAxis: { data: ["衬衫11111", ...
- Linux sudoers
xxx is not in the sudoers file.This incident will be reported.的解决方法 - xiaochaoyxc - 博客园http://www.cn ...
- Spring.profile配合Jenkins发布War包,实现开发、测试和生产环境的按需切换
前两篇不错 Spring.profile实现开发.测试和生产环境的配置和切换 - Strugglion - 博客园https://www.cnblogs.com/strugglion/p/709102 ...
- node exprss-session 和connect-mongo
let express = require('express'); let session = require('express-session'); let app = new express(); ...
- WebSocket推送
本篇博客只是记录websocket在自己的项目中的应用,只是记录,不做说明(后来替换为GoEasy了). /** * 握手的设置,这其实是为了获取session */ public class Get ...
- docker开启加速(第三篇)
前言: docker的镜像仓库在国外,下载会很慢,启用阿里云加速. 第一步:cd /etc/docker目录下,打开daemon.json 第二步:修改daemon.json文件,添加阿里云加速: ...
- Day 5-<补充> 类的的继承和查找顺序
类的继承于查找顺序: 在py2中,不继承object的类为经典类,经典类继承查找:深度优先. 在py3中,默认继承object,所以python3中都是新式类,新式类的继承查找:广度优先. 类的特殊属 ...
- npm install、npm install --save与npm install --save-dev区别
npm install X: 会把X包安装到node_modules目录中 不会修改package.json 之后运行npm install命令时,不会自动安装X npm install X –sav ...
- 创建虚拟目录失败,必须为服务器名称指定“localhost”
关于微信开发过程,远程调试后,再次打开vs出现项目加载失败的解决办法! 第一步: 第二步:打开编辑的页面,把下图这部分直接注释掉 ok了,再加载一次,就好了!