HDU 4777 Rabbit Kingdom(树状数组)
2015-09-26 09:07
393 查看
HDU 4777 Rabbit Kingdom
题目链接题意:给定一些序列。每次询问一个区间,求出这个区间和其它数字都互质的数的个数
#include <cstdio> #include <cstring> #include <algorithm> #include <vector> using namespace std; const int INF = 0x3f3f3f3f; typedef long long ll; const ll N = 200005; int n, m, vis , prime , pn = 0; void getprime() { for (ll i = 2; i < N; i++) { if (vis[i]) continue; prime[pn++] = i; for (ll j = i * i; j < N; j += i) vis[j] = 1; } } vector<int> g ; void getfac(int i) { g[i].clear(); int tmp; scanf("%d", &tmp); for (int j = 0; j < pn && prime[j] * prime[j] <= tmp; j++) { if (tmp % prime[j] == 0) { g[i].push_back(prime[j]); while (tmp % prime[j] == 0) tmp /= prime[j]; } } if (tmp != 1) g[i].push_back(tmp); } int v , L , R , ans , bit ; struct Query { int l, r, id; } q ; bool cmp(Query a, Query b) { return a.r < b.r; } #define lowbit(x) (x&(-x)) void add(int x, int v) { if (x == 0) return; while (x < N) { bit[x] += v; x += lowbit(x); } } int get(int x) { int ans = 0; while (x) { ans += bit[x]; x -= lowbit(x); } return ans; } int get(int l, int r) { return get(r) - get(l - 1); } vector<int> sv ; int main() { getprime(); while (~scanf("%d%d", &n, &m) && n) { memset(v, 0, sizeof(v)); for (int i = 1; i <= n; i++) { getfac(i); int left = 0; for (int j = 0; j < g[i].size(); j++) { left = max(left, v[g[i][j]]); v[g[i][j]] = i; } L[i] = left; } memset(v, INF, sizeof(v)); for (int i = n; i >= 1; i--) { int right = n + 1; for (int j = 0; j < g[i].size(); j++) { right = min(right, v[g[i][j]]); v[g[i][j]] = i; } R[i] = right; } for (int i = 0; i < m; i++) { scanf("%d%d", &q[i].l, &q[i].r); q[i].id = i; } for (int i = 1; i <= n; i++) sv[i].clear(); for (int i = 1; i <= n; i++) sv[R[i]].push_back(i); sort(q, q + m, cmp); memset(bit, 0, sizeof(bit)); int u = 1; for (int i = 0; i < m; i++) { while (u <= n && u <= q[i].r) { add(L[u], 1); for (int j = 0; j < sv[u].size(); j++) { int pv = sv[u][j]; add(L[pv], -1); add(pv, 1); } u++; } ans[q[i].id] = q[i].r - q[i].l + 1 - get(q[i].l, q[i].r); } for (int i = 0; i < m; i++) printf("%d\n", ans[i]); } return 0; }
思路:现处理出每一个位置的Li,Ri表示最多向左向右能有多少是保持都互质的,然后把询问按右区间排序,从左往右每次增加该位置的左端点Li,每次询问就询问满足Li。Ri都包括在这个区间内。所以询问Li到Ri的个数代表不满足的个数,然后每次到一个端点,假设有之前位置的Ri是这个位置。那么就把那个位置的Li减掉。而且标记掉这个点已经不可能符合标记为1
代码:
相关文章推荐
- 洛谷1164 小A点菜
- test7.19
- leetcode 277: Find the Celebrity
- dsp/bios初步了解
- 往年百度PC客户端研发笔试题(2)
- ORACLE AUTOMATIC STORAGE MANAGEMENT翻译-第二章 ASM instance(1)
- memcpy 函数
- test7.18
- C语言复习day1
- UI基础知识
- Cocos2d-x学习(一) Cocos2d-x2.2.6安装前准备
- 百度win10直通车怎么用?百度win10直通车下载和使用方法
- 移动互联网(一)短信和彩信界面开发包
- Java基础知识强化之集合框架笔记02:集合的继承体系图解
- eclipse 制作静态柱状图
- 为什么32的嘀嗒定时器在低功耗stop模式唤醒后会比较缓慢
- angularjs学习笔记之简单介绍
- js--url路径说明
- 于windows建筑物Cocos2d-x win32开发环境
- 如何在 Ubuntu 中安装 QGit 客户端