「SCOI2016」妖怪

题意

有 \(n\) 只妖怪,每只妖怪有攻击力 \(\text{atk}\) 和防御力 \(\text{dnf}\) ,在环境 \((a, b)\) 下,它可以把攻击力和防御力以 \(a : b\) 的代价呼唤,它的最强战斗力为互换后的攻击力与防御力的最大值。

现要给他们一种环境,使得它们的最强战斗力最小。答案保留四位小数。

\(1 \le n \le 10^6, 0 < \text{atk}, \text{dnf} \le 10^6\)

题解

首先,一个很显然的性质,如果把一只妖怪的两个属性看做二维平面上的一个点,那么在某一环境下妖怪的战斗力,也就是过这个点的某一条直线与 \(x\) 轴和 \(y\) 轴交点坐标之和。

于是题目所求就可以转化为,给定二位平面内的 \(n\) 个点,确定一个直线的斜率,使得分别过这 \(n\) 个点的 \(n\) 条直线的横纵坐标之和最大的直线尽可能小。

我们猜测一下,它其实关于斜率的函数图像是凸的,那么就是可以三分的,我们直接三分最值就好啦QAQ 复杂度是 \(O(n \log \epsilon^{-1})\) 的,特别好写。

为啥呢?

对于每一项展开得到 \(\text{atk}+\frac{\text{dnf}}{b}a + \text{dnf} + \frac{\text{atk}}{a} b\)

令 \(T=\frac{a}{b}\) 那么原式 \(=\text{atk}+T\text{dnf} + \text{dnf} + \frac{\text{atk}}{T}\) 这就是那个单峰的对勾函数, 把单峰函数复合为求最大值,发现也是个单峰函数,其实就是个凸的。

前面直接三分常数还是挺大的,我们有更好的做法。

于是我们可以先求出凸包,那么对答案造成贡献的点一定在凸包上。前面说了这个是对勾函数。于是我们分类讨论出函数的最小值即可。时间复杂度 \(O(n \log 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__)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_shadowfreopen ("2015.in", "r", stdin);freopen ("2015.out", "w", stdout);
#endif
}const double eps = 1e-13;const int N = 1e6 + 1e3;int n, atk[N], def[N];inline double f(double k) {double ans = .0;For (i, 1, n)chkmax(ans, atk[i] + def[i] - (k * atk[i] + def[i] / k));return ans;
}int main () {File();n = read();For (i, 1, n)atk[i] = read(), def[i] = read();double l = - 5, r = 0;while (r - l > eps) {double mid1 = (l + r) / 2.0,mid2 = (mid1 + r) / 2.0;if (f(mid1) < f(mid2)) r = mid2; else l = mid1;}printf ("%.4lf\n", f(l));return 0;}

凸壳

#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;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_shadowfreopen ("2015.in", "r", stdin);freopen ("2015.out", "w", stdout);
#endif
}const double eps = 1e-10, inf = 1e10;const int N = 1e6 + 1e3;struct Point {int x, y;inline double Min() {return x + y + 2 * sqrt(1ll * x * y);}inline double f(double k) {chkmin(k, -eps);return x + y - (x * k + y / k);}
};inline Point operator - (const Point &lhs, const Point &rhs) {return (Point) {lhs.x - rhs.x, lhs.y - rhs.y};
}double Slope (const Point &lhs, const Point &rhs) {if (lhs.x == rhs.x) return inf;return 1.0 * (rhs.y - lhs.y) / (rhs.x - lhs.x);
}inline ll Cross(Point a, Point b) { return 1ll * a.x * b.y - 1ll * a.y * b.x; }struct Cmp {inline bool operator () (const Point &lhs, const Point &rhs) const {return lhs.x != rhs.x ? lhs.x < rhs.x : lhs.y < rhs.y;}
};Point P[N], stk[N]; int top;inline bool Check(Point a, Point b, Point c) { return Cross(c - a, b - a) <= 0; }int main () {File();int n = read();For (i, 1, n)P[i].x = read(), P[i].y = read();sort(P + 1, P + n + 1, Cmp());stk[top = 1] = P[1];stk[top = 2] = P[2];For (i, 3, n) {while (top > 1 && Check(stk[top - 1], stk[top], P[i])) -- top; stk[++ top] = P[i];}double ans = inf;For (i, 1, top) {double pre = i > 1 ? Slope(stk[i - 1], stk[i]) : eps, suf = i < top ? Slope(stk[i], stk[i + 1]) : - inf;chkmin(pre, .0); chkmin(suf, .0);double res = min(stk[i].f(pre), stk[i].f(suf)), Best = - sqrt(1.0 * stk[i].y / stk[i].x);if (suf < Best && Best < pre) chkmin(res, stk[i].Min()); chkmin(ans, res);}printf ("%.4lf\n", ans);return 0;}

「SCOI2016」美味

题意

有一个长度为 \(n\) 的序列 \(\{a_i\}\) 。

有 \(q\) 次询问,每次四个整数 \(b, x, l, r\) ,可以把 \(b\) 变成 \(b \text{ xor } (a_i + x)\) (只能变一次),其中 \(i \in [l, r]\) ,问 \(b\) 的最大值。

$ 1 \leq n \leq 2 \times 10 ^ 5, 0 \leq a_i, b_i, x_i < 10 ^ 5, 1 \leq m \leq 10 ^ 5 $

题解

如果 \(x = 0\) 那么就是区间 \(01-Trie\) 套 std :: set 啦。

但是有 \(x\) 怎么做呢?其实还是可以类似于 \(01-Trie\) 。

我们按位考虑,我们从高到低考虑,看 \(b\) 的每一位是否能异或出 \(1\) 。

不难发现,当前的询问会对到一道连续区间 \([l, r]\) 。

这下问题就转化为,区间查询权值在一段区间内的数是否存在,这个直接用主席树维护即可。

复杂度是 \(O(n \log n \log a_i)\) 的。

总结

可以考虑用数据结构去模拟另外一个数据结构。

代码

#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_shadowfreopen ("2016.in", "r", stdin);freopen ("2016.out", "w", stdout);
#endif
}const int N = 2e5 + 1e3;template<int Maxn>
struct ChairMan_Tree {int tot[Maxn], ls[Maxn], rs[Maxn], Size = 0;inline void Update(int &o, int pre, int l, int r, int up) {tot[o = ++ Size] = tot[pre] + 1;ls[o] = ls[pre]; rs[o] = rs[pre]; if (l == r) return ;int mid = (l + r) >> 1;if (up <= mid) Update(ls[o], ls[pre], l, mid, up);else Update(rs[o], rs[pre], mid + 1, r, up);}bool Query(int x, int y, int l, int r, int ql, int qr) {if (ql <= l && r <= qr) return tot[y] - tot[x];int mid = (l + r) >> 1;if (ql <= mid && Query(ls[x], ls[y], l, mid, ql, qr)) return true;if (qr > mid && Query(rs[x], rs[y], mid + 1, r, ql, qr)) return true;return false;}};ChairMan_Tree<int(4 * N * log2(N))> T;int n, m, rt[N], a[N];int main () {File();n = read(); m = read();For (i, 1, n) a[i] = read();int lim = *max_element(a + 1, a + n + 1);For (i, 1, n)T.Update(rt[i], rt[i - 1], 0, lim, a[i]);while (m --) {int b = read(), x = read(), l = read() - 1, r = read();int len = ceil(log2(max(b, lim + x))), ans = 0;Fordown (i, len, 0) {int need = ((b >> i) & 1) ^ 1, L, R;L = ans + (need << i) - x;R = ans + (1 << i + need) - 1 - x;ans |= (!need ^ (L <= lim && R >= 0 && T.Query(rt[l], rt[r], 0, lim, L, R))) << i;}printf ("%d\n", ans ^ b);}return 0;}

「SCOI2016」围棋

题意

有 \(q\) 次询问,每次给你一个 \(2 \times c\) 的模板,问有多少个 \(n \times m\) 只包含 W, B, X 的棋盘至少包含一个模板。

$ n \leq 100, m \leq 12, c \leq 6, q \leq 5 $

题解

\(m\) 很小,显然是考虑轮廓线 \(dp\) 。

一个很直观的想法是记下连续两行上的状态,直接做,复杂度是 \(O(qnm3^{2m})\) 的,显然过不去啦。

其实很多状态是没有意义的,我们只需要记上面一圈轮廓线的对应的结尾是否能匹配上 \(S_1\) 即可。我们模板上面一排为 \(S_1\) 下面一排为 \(S_2\) 。

然后这样状态显然还不够,因为你无法去转移到后面的状态,对于匹配问题我们只需要多记下最后一个位置匹配到最远的字符就好啦,然后转移就用 \(\text{KMP}\) 去转。

具体来说,令 f[i][j][S][x][y] 为到 \(i\) 行 \(j\) 列,轮廓线能匹配上的状态为 \(S\) ,\((i, j)\) 结尾的串匹配到 \(S_1\) 的第 \(x\) 位,\(S_2\) 的第 \(y\) 位。

其实状态没有那么满,用个哈希表转移一下,跑的挺快的。复杂度是 \(O(nm2^{m}c^2)\) 。

总结

dp 一定要记得压状态鸭!!

代码

至于实现,可以记不合法的方案数,最后用 \(3^{nm}\) 减掉即可。其实记合法的也一样。。。

#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 Rep(i, r) for (register int i = (0), i##end = (int)(r); 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) << endlusing 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_shadowfreopen ("2017.in", "r", stdin);freopen ("2017.out", "w", stdout);
#endif
}const int N = 13, Mod = 1e9 + 7;int n, m, c, q;inline int encode(int S, int x, int y) {return S * (c + 1) * (c + 1) + x * (c + 1) + y;
}inline void decode(int code, int &S, int &x, int &y) {S = code / (c + 1) / (c + 1);x = code / (c + 1) % (c + 1);y = code % (c + 1);
}unordered_map<int, int> M[2];char S1[N], S2[N]; int fail1[N], fail2[N];inline void get_fail(char *S, int *fail) {fail[1] = 0;For (i, 2, strlen(S + 1)) {int j = fail[i - 1];while (j && S[j + 1] != S[i]) j = fail[j];fail[i] = j + (S[i] == S[j + 1]);}
}inline int kmp(char *S, int *fail, int pos, char T) {while (pos && S[pos + 1] != T) pos = fail[pos];return pos + (S[pos + 1] == T);
}inline void Add(int &a, int b) {if ((a += b) >= Mod) a -= Mod;
}int cur;
inline void Insert(int S, int x, int y, int val) {Add(M[cur][encode(S, x, y)], val);
}char ch[3] = {'W', 'B', 'X'};int main() {File();n = read(); m = read(); c = read(); q = read();while (q --) {scanf ("%s", S1 + 1); get_fail(S1, fail1);scanf ("%s", S2 + 1); get_fail(S2, fail2);M[0].clear(); M[1].clear();cur = 1; Insert(0, 0, 0, 1); cur ^= 1;int ans = 0;For (i, 1, n) For (j, 1, m) {for (auto it : M[cur ^ 1]) {int S, x, y, val = it.second;decode(it.first, S, x, y);Rep (k, 3) {int nx = kmp(S1, fail1, x, ch[k]);int ny = kmp(S2, fail2, y, ch[k]);if ((S & 1) && ny == c) continue;int nS = (S >> 1) | ((nx == c) << (m - 1));if (j == m) {nx = ny = 0;if (i == n) Add(ans, val);}Insert(nS, nx, ny, val);}}M[cur ^= 1].clear();}int res = 1;For (i, 1, n * m) res = res * 3ll % Mod;printf ("%d\n", (res - ans + Mod) % Mod);}return 0;}

转载于:https://www.cnblogs.com/zjp-shadow/p/10357479.html

SCOI2016 Day2 简要题解相关推荐

  1. AHOI2013 Round2 Day2 简要题解

    第一题: 第一问可以用划分树或主席树在O(nlog2n)内做出来. 第二问可以用树状数组套主席树在O(nlog2n)内做出来. 我的代码太挫了,空间刚刚卡过...(在bzoj上) 第二题: 分治,将询 ...

  2. Noip 2014酱油记+简要题解

    好吧,day2T1把d默认为1也是醉了,现在只能期待数据弱然后怒卡一等线吧QAQ Day0 第一次下午出发啊真是不错,才2小时左右就到了233,在车上把sao和fate补掉就到了= = 然后到宾馆之后 ...

  3. 杂题记录及简要题解(一)

    一些前几天做过的还不错的但是不是太想专门花一整篇博客的篇幅去写的题就简要地记录在这里. 说是简要题解,其实写得还是挺详细的.之后的杂题记录可能就会写得简略一点. CF1060E Sergey and ...

  4. c语言1106回文数,Codeforces 1106 简要题解

    A题 传送门 读错题还能过样例我给自己点个赞. 题意简述:给一个010101网格SSS,问满足Si,j=Si+1,j+1=Si+1,j−1=Si−1,j−1=Si−1,j+1S_{i,j}=S_{i+ ...

  5. 湖南省第十届蓝狐网络杯大学生计算机程序设计竞赛,2019年湖南省大学生计算机程序设计竞赛 (HNCPC2019) 简要题解...

    2019年湖南省大学生计算机程序设计竞赛 (HNCPC2019) 简要题解 update10.01 突然发现叉姐把这场的题传到牛客上了,现在大家可以有地方提交了呢. 不知道该干什么所以就来水一篇题解 ...

  6. BJOI2018简要题解

    BJOI2018简要题解 D1T1 二进制 题意 pupil 发现对于一个十进制数,无论怎么将其的数字重新排列,均不影响其是不是 \(3\) 的倍数.他想研究对于二进制,是否也有类似的性质. 于是他生 ...

  7. 【NOI2019十二省联合省选】部分题简要题解

    Day 1 T1 异或粽子 题意:给出一个长为n的序列,选择K个不完全重合的区间使得每个区间的异或值的总和最大. 题解:先做一个前缀异或和,对于每一个右端点我们记录三元组(l,r,x)表示在左端点在\ ...

  8. Codeforces 1110 简要题解

    文章目录 A题 B题 C题 D题 E题 F题 G题 传送门 众所周知ldxoildxoildxoi这种菜鸡选手是不会写HHH题的,因此该篇博客只有AAA题至GGG题的题解,实在抱歉. A题 传送门 题 ...

  9. 【HNOI2019】部分题简要题解

    题意懒得写了 LOJ Day 1 T1 鱼 个人做法比较猎奇,如果有哪位大佬会证明能分享一下的话感激不尽. 题解:枚举鱼尾和鱼身的交点D,将所有其他点按照到D的距离排序,距离相同的分一组. 感性的理解 ...

最新文章

  1. R二项分布检验:双尾二项检验(Two-tailed Binomial Test)、左尾二项检验(Left-tailed Binomial Test)、右尾二项检验
  2. linux shell less 命令---转
  3. Java获得随机数字
  4. 帮中国修长城前,英特尔还用AI追踪北极熊、保护鲸鱼
  5. Centos 中如何快速定制二进制的内核 RPM 包
  6. python高斯求和_利用Python进行数据分析(3)- 列表、元组、字典、集合
  7. 读大师的书 说自己的话——《传世经典书丛评注版》邀你来点评
  8. jackson的简单实用实例(json)
  9. 阿里云OpenSearch使用体验V1
  10. 百度如流智能工作平台2.0发布 聚焦智能组织
  11. 基于hyperleger fabric区块链的校园化妆品交易平台搭建
  12. 微信指纹java.lang_微信小程序调用指纹验证
  13. 愿所有程序都有接口,愿所有接口说明都通俗易懂,更新及时
  14. MySQL索引机制-图灵教育诸葛老师
  15. 电位器和编码器的区别
  16. 虚拟机安装kali 时的默认密码(官网vmx 文件源)
  17. ExcelReport(Excel报表系统)
  18. 【Scratch课件-广播并等待】百米赛跑
  19. 匹维托客户关系对于机构资产管理
  20. 几款主流的浏览器速度测试

热门文章

  1. 在mm32f3270为micropython移植utime模块
  2. 学习笔记--深度学习入门--基于Pyrhon的理论与实现--[日]斋藤康毅 -- 持续更新中
  3. [Pytorch] 学习记录(七)MNIST多分类问题
  4. React实现插槽(solt)
  5. ORACLE中用for in 使用cursor 游标
  6. Android集成佳博热敏打印机打印小票对齐问题
  7. Java学习笔记01
  8. 深度学习之美——深度学习基本介绍
  9. 燕十八老师高级JS之this详解 学习笔记
  10. Python Selenium+PhantomJs 爬煎蛋妹子图