13杭州区域赛现场赛Rabbit Kingdom(树状数组+离线)

题意:给你一个长度数列,再给你m个询问(一个区间),问你在这个区间里面有多少个数与其他的数都互质。

解题思路:你看这种类型的题目都可以肯定这是
离线+树状数组(线段树)。主要就是他的更新信息。这里我的处理是先把1-200000(每个数的范围)数里面所有的质因子求出来。然后从后往前遍历数组。会出现以下几种情况

1.a[k]的质因子在后面出现过而【更新标记】 和【被更新标记】 都为假

2.a[k]的质因子在后面出现过的那个位置 I   【更新标记】为 真

3.a[k]的质因子在后面出现过且那个位置 I  【被更新标记】
 为真 。

如果只出现 1 这种情况,那么这个位置   +1,【更新标记】 变为真;

如果只出现 2 这种情况, 那么对这个位置不更新。

如果出现 3 这种情况, 那么  I  的被更新位置 -1  ,I位置 +1  ,且
I的被更新标记变为假。

在这个过程中,a[k]的所有质因子的 最新位置 都变为K ,再找到到离 a【K】 最近的和它 不互质的数 a【X】 把K的
【被更新标记】变为  X,再在X位置 +1

(上面所有的操作都是为了使得记数不 错误)

最后的答案就是   区间内数的个数 - 区间求的和。

解题代码:

  1 // File Name: c.cpp
2 // Author: darkdream
3 // Created Time: 2014年05月07日 星期三 17时07分23秒
4
5 #include<vector>
6 #include<list>
7 #include<map>
8 #include<set>
9 #include<deque>
10 #include<stack>
11 #include<bitset>
12 #include<algorithm>
13 #include<functional>
14 #include<numeric>
15 #include<utility>
16 #include<sstream>
17 #include<iostream>
18 #include<iomanip>
19 #include<cstdio>
20 #include<cmath>
21 #include<cstdlib>
22 #include<cstring>
23 #include<ctime>
24
25 using namespace std;
26 #define MAXN 200005
27
28
29 int a[MAXN];
30 struct lr{
31 int l,r,num;
32 }q[MAXN];
33 int cmp(lr a, lr b)
34 {
35 return a.l > b.l;
36 }
37 int tree[MAXN];
38 int lowbit(int x)
39 {
40 return x&(-x);
41 }
42 int getsum(int l,int k)
43 {
44 int sum = 0 ;
45 while(k >= l )
46 {
47 sum += tree[k];
48 k -= lowbit(k);
49 }
50 return sum ;
51 }
52 int n;
53 int hs[MAXN];
54 void update(int k ,int v )
55 {
56 // printf("%d\n",k);
57 while(k <= n)
58 {
59 tree[k] += v;
60 k += lowbit(k);
61 }
62
63 }
64 int ans[MAXN];
65 int prime[MAXN][20];
66 int num[MAXN];
67 int last[MAXN];
68 void solve(){
69 memset(num,0,sizeof(num));
70 memset(hs,0,sizeof(hs));
71 for(int i = 2 ;i <= 200000;i ++)
72 {
73 if(hs[i] == 0 )
74 {
75 int k = i;
76 while(k <= 200000)
77 {
78 num[k] ++ ;
79 prime[k][num[k]] = i ;
80 hs[k] = 1;
81 k += i ;
82 }
83 }
84 }
85 }
86 int isupdate[MAXN];
87 int cmp1(int a, int b)
88 {
89 return a < b ;
90 }
91 int main(){
92 //freopen("intpu.in","r",stdin);
93 int m ;
94 solve();
95 //printf("***\n");
96 while(scanf("%d %d", &n,&m) != EOF)
97 {
98 if(n == 0 && m == 0 )
99 break;
100 memset(tree,0,sizeof(tree));
101 memset(q,0,sizeof(q));
102
103
104 for(int i = 1;i <= n;i ++)
105 scanf("%d",&a[i]);
106 for(int i = 1;i <= m;i ++)
107 {
108 scanf("%d %d",&q[i].l,&q[i].r);
109 q[i].num = i;
110 }
111 sort(q+1,q+m+1,cmp);
112
113 int p = 1;
114 memset(hs,0,sizeof(hs));
115 memset(last,0,sizeof(last));
116 memset(isupdate,0,sizeof(isupdate));
117 //memset(q,0,sizeof(q));
118 for(int i = n;i >= 1 ;--i)
119 {
120 int ta[20];
121 int tanum = 0 ;
122 memset(ta,0,sizeof(ta));
123 for(int j = 1; j <= num[a[i]]; ++j )
124 {
125 int temp = prime[a[i]][j];
126 if(hs[temp])
127 {
128 tanum ++ ;
129 ta[tanum] = hs[temp];
130 }
131 hs[temp] = i ;
132 }
133 if(tanum)
134 {
135 sort(ta+1,ta+tanum+1,cmp1);
136 int min = ta[1];
137 for(int j = 1;j <= tanum;j ++)
138 {
139 if(ta[j]!= ta[j-1])
140 {
141 if(last[ta[j]])
142 {
143 update(last[ta[j]],-1);
144 update(ta[j],1);
145 last[ta[j]] = 0 ;
146 }else {
147 if(!isupdate[ta[j]])
148 {
149 update(ta[j],1);
150 isupdate[ta[j]] = 1 ;
151 }
152 }
153 if(ta[j] < min)
154 min = ta[j];
155 }
156 }
157 update(min,1);
158 isupdate[min] = 1;
159 last[i] = min;
160 isupdate[i] = 1;
161
162 }
163 while(q[p].l == i )
164 {
165 ans[q[p].num] = (q[p].r - q[p].l +1) - getsum(q[p].l,q[p].r);
166 p++;
167 }
168 }
169 for(int i = 1;i <= m;++i)
170 printf("%d\n",ans[i]);
171 }
172 return 0;
173 }

很难

13杭州区域赛现场赛Rabbit Kingdom(树状数组+离线),布布扣,bubuko.com

时间: 2024-09-29 00:43:25

13杭州区域赛现场赛Rabbit Kingdom(树状数组+离线)的相关文章

hdu 4777 Rabbit Kingdom(树状数组)

题目链接:hdu 4777 Rabbit Kingdom 题目大意:一个兔子王国,有N只兔子,每只兔子有一个重量,如果两只兔子的重量不互质,那么就会干架,现在国王想将l r之间的兔子关进监狱,它想知道会有多少只兔子不会和别的兔子干架. 解题思路:预处理出每只兔子的L,R表示向左和向右最近会与该兔子发生冲突的兔子,预处理的时候只要将每只兔子的重量分解成质因子后遍历两遍. 对于询问,将询问按照右区间排序,碰到i,则L位置+1,碰到R,则i位置+1,L位置-1.(如果L ≤ l && r ≤ R

hdu4777 Rabbit Kingdom 树状数组+区间操作+素数打表

题目大意:给N个数,有M个查询,问区间[L,R]之间有多少个数与这个区间内的其他数都互质. 思路:dp显然很难搞,既然是求区间就试试每一个数最大可以对答案产生贡献的区间,即预处理出一个数在(lp,rp)内始终与其他数互质的最大区间 则lp和rp分别为左边和右边第一个与他不互质的数的位置 处理的时候素数打表然后从左到右始终更新对于某一个素因子出现的最右的位置然后更新l,r,可以做到 然后就是把查询按l从小到大排序,这样的话每处理一个新的查询,对于在这个查询的 l 左边的数就可以不用考虑了 然后我们

UVA 12663 第九届省赛 高桥与低桥 树状数组

1 #include <cstdio> 2 #include <math.h> 3 #include <iostream> 4 #include <cstring> 5 #include <cstdlib> 6 #include <algorithm> 7 using namespace std; 8 9 const int maxn = 1e5+10; 10 int c[maxn], a[maxn]; 11 int lowbit(i

HDU 4791 Alice&#39;s Print Service(2013长沙区域赛现场赛A题)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4791 解题报告:打印店提供打印纸张服务,需要收取费用,输入格式是s1 p1 s2 p2 s3 p3...表示打印区间s1到s2张纸的单价是p1,打印区间s2 到s3的单价是p2....最后是sn到无穷大的单价是pn,让你求打印k张纸的总费用最少是多少?有m次查询. 因为s1*p1 > s2 * p2 > s3*p3......,很显然,加入k所在的那个区间是第x个区间,那么最低费用要么是k * p

13年山东省赛 Boring Counting(离线树状数组or主席树+二分or划分树+二分)

转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud 2224: Boring Counting Time Limit: 3 Sec  Memory Limit: 128 MB Description In this problem you are given a number sequence P consisting of N integer and Pi is the ith element in the sequence.

hdu 4777 Rabbit Kingdom(离线树状数组&amp;思维)

Rabbit Kingdom Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 964    Accepted Submission(s): 315 Problem Description Long long ago, there was an ancient rabbit kingdom in the forest. Every rab

北邮校赛 F. Gabriel&#39;s Pocket Money(树状数组)

F. Gabriel's Pocket Money 2017- BUPT Collegiate Programming Contest - sync 时间限制 2000 ms 内存限制 65536 KB 题目描述 For centuries, Heaven has required its young angels to live and study among humans in order to become full-fledged angels. This is no different

Ryuji doesn&#39;t want to study 2018徐州icpc网络赛 树状数组

Ryuji is not a good student, and he doesn't want to study. But there are n books he should learn, each book has its knowledge a[i]a[i]. Unfortunately, the longer he learns, the fewer he gets. That means, if he reads books from ll to rr, he will get a

hdu 1754 I Hate It(树状数组区间求最值)2007省赛集训队练习赛(6)_linle专场

题意: 输入一行数字,查询第i个数到第j个数之间的最大值.可以修改其中的某个数的值. 输入: 包含多组输入数据. 每组输入首行两个整数n,m.表示共有n个数,m次操作. 接下来一行包含n个整数. 接下来m行,每行包含一个字母s,两个整数a,b. 当s为’Q’,表示查询第a个数到第b个数之间的最大值. 当s为’U’,表示将第a个数更改为b. 输出: 每次查询输出一个结果,每次输出占一行. 题解: 点修改区间求最值,可以用树状数组模板. 具体见代码—— 1 #include <cstdio> 2