2015多校赛第一场
2015-07-22 13:58
127 查看
A题
给你个n个数的数列,找出所有区间内不能被区间其他数整除的数的个数之和。
B题
RMQ问题,ST算法+二分
先用ST算法求出区间最值(最大值和最小值),然后枚举区间左端点,二分右端点
给你个n个数的数列,找出所有区间内不能被区间其他数整除的数的个数之和。
#pragma warning(disable:4996) #include <iostream> #include <cstdio> #include <vector> #include <algorithm> #define mod 1000000000+7 #define N 100000+5 using namespace std; int x , y , a , p[10005]; vector<int>mul[10005]; int n; int main(){ //填充因子vector for (int i = 1; i <= 10000; i++){ for (int j = 1; j <= i; j++){ if (i%j == 0)mul[i].push_back(j); } } while (scanf("%d", &n) != EOF){ for (int i = 1; i <= n; i++){ scanf("%d", a + i); //初始化x,y数组 x[i] = 0; y[i] = n + 1; } //此时p[i]表示i出现的左最靠近当前数字的位置 memset(p, 0, sizeof(p)); for (int i = 1; i <= n; i++){ int tmp = 0; for (int j = 0; j < mul[a[i]].size(); j++){ tmp = max(tmp, p[mul[a[i]][j]]); } //填充x数组 x[i] = tmp; //更新p数组 p[a[i]] = i; } for (int i = 0; i < 10005; i++)p[i] = n + 1; for (int i = n; i >= 1; i--){ int tmp = n + 1; for (int j = 0; j < mul[a[i]].size(); j++){ tmp = min(tmp, p[mul[a[i]][j]]); } //填充y数组 y[i] = tmp; //更新p数组 p[a[i]] = i; } int ans = 0; for (int i = 1; i <= n; i++){ ans += ((i - x[i])*(y[i] - i)); ans %= mod; } cout << ans << endl; } return 0; }
B题
RMQ问题,ST算法+二分
先用ST算法求出区间最值(最大值和最小值),然后枚举区间左端点,二分右端点
#include <iostream> #include <algorithm> #include <cmath> #define N 100000+50 using namespace std; int a ; int maxx [20], minx [20]; void rmq(int n){ for (int i = 1; i <= n; i++)maxx[i][0] = minx[i][0] = a[i]; for (int j = 1; j < 20; j++){ for (int i = 1; i <= n; i++){ if (i + (1 << j - 1) <= n){ maxx[i][j] = max(maxx[i][j - 1], maxx[i + (1 << j - 1)][j - 1]); minx[i][j] = min(minx[i][j - 1], minx[i + (1 << j - 1)][j - 1]); } } } } int query(int l, int r){ int base = 0; while ((1 << (base + 1)) < (r - l + 1)) base++; int maxn = max(maxx[l][base], maxx[r + 1 - (1 << base)][base]); int minn = min(minx[l][base], minx[r + 1 - (1 << base)][base]); return maxn - minn; } int main(){ int t; cin >> t; while (t--){ int n, k; cin >> n >> k; for (int i = 1; i <= n; i++)cin >> a[i]; rmq(n); long long ans = 0; for (int i = 1; i <= n; i++){ int l = i, r = n; while (l <= r){ int mid = (l + r) / 2; if (query(i, mid) >= k) r = mid - 1; else l = mid + 1; } ans += (r - i + 1); } cout << ans << endl; } return 0; }
相关文章推荐
- WNDCLASS结构中cbWndExtra数据成员的作用
- 如何在页面打开后根据条件让EditorGridPanel的某一行的复选框默认选中?
- java List.subList()方法类似分页分批处理数据
- html from嵌套from
- 夏令营第一期——【一】迎接初升朝阳的序幕
- Linux netlink
- LeetCode Bitwise AND of Numbers Range
- Android SDK在线更新镜像服务器
- HDOJ4552怪盗基德的挑战书
- 关于self.与_的区别
- UML软件建模学习与开发基本概念汇总
- Web前端开发工程师--面试要求
- 样式表写法
- Java通过XML Schema校验XML
- AngularJS2.0 教程系列(一)
- ubuntu下查看windows文件乱码
- 【算法】对一个20GB大的文件排序
- 一、nginx介绍及安装
- linux 下tar 打包分割文件和解压文件
- GRE写作必备句型