F. Monkeying Around   维护点在多少个线段上

http://codeforces.com/gym/101350/problem/F

题意:有m个笑话,每个笑话的区间是[L, R],笑话种类有1e5,一开始所有猴子都在凳子上,听到一个笑话,就倒下,但是如果是听过的笑话,就重新回到凳子上。问最终有多少个猴子在凳子上。

相当于有1e5个线段,如果我们能知道第i个猴子,被多少个线段覆盖了,那么可以找出那些线段中的最后那一条,就是最后覆盖上去的那一条,那条线段是哪一个笑话,设为k,如果这个笑话覆盖这个猴子的次数 > 1,那么这个猴子将会回到凳子上。也就是只和最后一步有关

那么,假如有线段:

按左端点排序:[1, 100], [2, 2]  ,一个扫描变量p1 = 1开始

按右端点排序:[2, 2],  [1, 100], 一个扫描变量p2 = 1开始

就能很快判断到第i个猴子被那些线段覆盖了。

按顺序枚举每一个猴子i,比如i = 2

那么,把i >= segment1[p1].L的都表明这条线段能覆盖i

吧i > segment2[p2].R的都表明这条线段已经离开了i

然后统计即可。

#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;
const int maxn = 2e5 + 20;
struct Node {int L, R, id;
}one[maxn], two[maxn];
bool cmp1(struct Node a, struct Node b) {return a.L < b.L;
}
bool cmp2(struct Node a, struct Node b) {return a.R < b.R;
}
int idForJoke[maxn];
int has[maxn];
set<int>ss;
void work() {ss.clear();memset(has, 0, sizeof has);int n, m;scanf("%d%d", &n, &m);for (int i = 1; i <= m; ++i) {int pos, joke, dis;scanf("%d%d%d", &pos, &joke, &dis);one[i].L = max(1, pos - dis), one[i].R = min(n, pos + dis), one[i].id = i;two[i] = one[i];idForJoke[i] = joke;}sort(one + 1, one + 1 + m, cmp1);sort(two + 1, two + 1 + m, cmp2);int ans = 0, p1 = 1, p2 = 1;for (int i = 1; i <= n; ++i) {while (p1 <= m && i >= one[p1].L) {ss.insert(one[p1].id);has[idForJoke[one[p1].id]]++;++p1;}while (p2 <= m && i > two[p2].R) {ss.erase(two[p2].id);has[idForJoke[two[p2].id]]--;++p2;}if (ss.size()) {ans += has[idForJoke[*ss.rbegin()]] > 1;} else ans++;}printf("%d\n", ans);
}int main() {
#ifdef localfreopen("data.txt", "r", stdin);
//    freopen("data.txt", "w", stdout);
#endifint t;scanf("%d", &t);while (t--) work();return 0;
}

View Code

G. Snake Rana  容斥原理 + 数学

题意是给定一个n * m(n, m <= 1e4)的地图,有k <= 20个污点,问有多少个子矩形,不包含任何一个污点

首先要知道n * m的矩形里面,一共有多少个子矩形。

对于列来说,可以选择边长是1, 2, ... m,分别有m种、m - 1种、m - 2 ... 1种选法。

对于行来说,可以选择边长是1, 2, ....n, 分别有n种、n - 1种,....1种选法。

所以一共(1 + .... + n) * (1 + .... + m) = (n + 1) * n / 2 * (m + 1) * m / 2种

1 << k暴力枚举哪一个点在里面,容斥原理奇减偶加

若包含x个点,那这x个点肯定围成一个矩形,那么有多少个矩形包含这个矩形呢?

如法炮制,算出在y方向,左右扩展能有多少个矩形,x方向,上下扩展能有多少种可能,然后相乘即可。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <bitset>
LL n, m;
int k;
const int maxn = 20 + 2;
int x[maxn], y[maxn];
LL ans;
void dfs(int cur, int sel, int x1, int y1, int x2, int y2) {if (cur == k + 1) {if (!sel) return;LL res = (x1) * (n - x2 + 1) * (y1) * (m - y2 + 1);if (sel & 1) ans -= res;else ans += res;return;}dfs(cur + 1, sel + 1, min(x1, x[cur]), min(y1, y[cur]), max(x2, x[cur]), max(y2, y[cur]));dfs(cur + 1, sel, x1, y1, x2, y2);
}void work() {scanf("%d%d%d", &n, &m, &k);for (int i = 1; i <= k; ++i) {scanf("%d%d", &x[i], &y[i]);}ans = (n + 1) * n / 2 * (m + 1) * m / 2;dfs(1, 0, inf, inf, -inf, -inf);cout << ans << endl;
}int main() {
#ifdef localfreopen("data.txt", "r", stdin);
//    freopen("data.txt", "w", stdout);
#endifint t;scanf("%d", &t);while (t--) work();return 0;
}

View Code

I. Mirrored String II   简单manacher变种不写题解了。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <bitset>
#include <time.h>
const int maxn = 5e3 + 20;
char str[maxn];
bool book[maxn];
int p[maxn];
int manacher(char str[], int lenstr) {str[0] = '*';for (int i = lenstr; i >= 0; --i) {str[i + i + 2] = str[i + 1];str[i + i + 1] = '#';}int id = 0, maxLen = 0;for (int i = 2; i <= 2 * lenstr + 1; ++i) {if (!book[str[i]]) {p[i] = 0;continue;}if (p[id] + id > i) {p[i] = min(p[id] + id - i, p[2 * id - i]);} else p[i] = 1;while (str[i + p[i]] == str[i - p[i]] && (book[str[i - p[i]]] || str[i - p[i]] == '#')) ++p[i];if (p[id] + id < p[i] + i) id = i;maxLen = max(maxLen, p[i]);}return maxLen - 1;
}
void work() {scanf("%s", str + 1);int lenstr = strlen(str + 1);bool flag = false;for (int i = 1; i <= lenstr; ++i) {if (book[str[i]]) {flag = true;break;}}if (!flag) {printf("0\n");return;}printf("%d\n", manacher(str, lenstr));
}

I

A题待补,还有一题好像是防ak还没看,其他都是简单题,不过还是挺有意思

转载于:https://www.cnblogs.com/liuweimingcprogram/p/6958428.html

2017 ACM Arabella Collegiate Programming Contest div2的题,部分题目写个题解相关推荐

  1. 2015 ACM Arabella Collegiate Programming Contest(F题)

    F. Palindrome [ Color: Pink ] A string is palindrome if it can be read the same way in either direct ...

  2. 2017 ACM Arabella Collegiate Programming Contest(solved 11/13)

    省选考前单挑做点ACM练练细节还是很不错的嘛- 福利:http://codeforces.com/gym/101350 先来放上惨不忍睹的virtual participate成绩(中间跑去食堂吃饭于 ...

  3. 2017 ACM Arabella Collegiate Programming Contest G. Snake Rana GYM101350G

    先算一下总的子矩阵个数 总共最多只有20个点 状压一下然后枚举 容斥一下 把求出来的答案减去包含1个点的子矩阵再加上包含2个点的减去3个点的-- #include <iostream> # ...

  4. 2017 ACM Arabella Collegiate Programming Contest

    Gym101350A. Sherlock Bones 题目大意: 给定一个长度为 \(n\) 的 \(01\) 序列 \(\{s_n\}\),定义 \(F(i, j)\) 表示序列第 \(i\) 项到 ...

  5. 【容斥】2017 ACM Arabella Collegiate Programming Contest

    比赛连接 G. Snake Rana Old Macdonald wants to build a new hen house for his hens. He buys a new rectangu ...

  6. 2017 ACM Arabella Collegiate Programming Contest E. Competitive Seagulls GYM101350E

    博弈经典套路 考虑把可选择的操作变成2个相同的 然后跟着对手操作 为奇数的时候选一个奇数把两边留出相同长度的白色 为偶数的时候选一个2把两边留出相同长度的白色 那么只有2 和 3 是不可以的 int ...

  7. 2017 ACM Arabella Collegiate Programming Contest(solved 9/13, complex 12/13)

    A.Sherlock Bones 题意: 给出长度为n的01串,问f(i,j)=f(j,k),(i<j<k)的i,j,k取值种数.其中f(i,j)表示[i,j]内1的个数, 且s[j]必须 ...

  8. 2017 ACM Arabella Collegiate Programming Contest A. Sherlock Bones GYM101350A

    把问题转换为求区间内1为奇数的区间有多少个 那么直接记录从1开始为奇数和偶数的区间有多少就算出这个了 但是有不合法的就是只有1个1的区间 所以再减一下 重复的再加回来 #include <ios ...

  9. 2017 ACM Arabella Collegiate Programming Contest F. Monkeying Around GYM101350F

    对单个点考虑 实际上每个点的结果只被最后的那种操作影响 那么处理一下每个点对应的最后一个操作种类 然后对每个种类都和对应的点都检查一下是否被操作了2次 转化成n个点 m个区间 多少点被覆盖>=2 ...

最新文章

  1. 用父节点表示法表示一棵树
  2. 别学前端了!前端程序员:凭啥??网友:来钱太快你会飘!
  3. 每天60秒读懂世界20211127
  4. linux应用之----进程通信
  5. angular 模块构建_通过构建全栈应用程序学习Angular 6
  6. 【Java】四种方法复制视频文件比较
  7. 4373支队伍报名2020数字中国创新大赛-数字政府赛道 数字战“疫”彰显社会责任...
  8. Linux学习笔记014---文件及文件夹权限设置_以及文件、文件夹的删除_移动_复制操作
  9. Kuberentes-入门
  10. Access中的模糊查询
  11. Spring IOC整理
  12. C语言:创建各类三角形图案
  13. 解读京东“拉黑门”:被拐弯的真相
  14. 共享花店App开发亮点解析
  15. ios 判断手机角度_IOS 判断iPhone刘海屏
  16. 高端访谈实录:访思科英国CEO菲尔·史密斯
  17. Method XXX does not exist.
  18. 简单的方法Android的数据恢复你的Andr​​oid手机
  19. 关于如何把图片放入VS 中并且引用的方法.
  20. 关于Eslint语法检查报“error Extra semicolon semi”错误的解决办法

热门文章

  1. Qt resizeEvent 控件居中设置
  2. 未与信任 SQL Server 连接相关联
  3. 郁闷好久的电脑问题终于搞定---电脑经常死机
  4. 一条SQL查询语句是如何执行的? MySql杂谈
  5. mysql的入门基础操作
  6. 关于Web面试的基础知识点--Html+Css(四)
  7. 老码农的Java干货资源
  8. STM32F407之资源
  9. 软工总结暨团队成员自评(胡骏)
  10. android 豆瓣客户端 视频