Codeforces Round #271 (Div. 2) F 线段树+pair
来源:互联网 发布:vm12虚拟机安装mac os 编辑:程序博客网 时间:2024/05/18 15:28
链接:戳这里
F. Ant colony
time limit per test1 second
memory limit per test256 megabytes
inputstandard input
outputstandard output
Mole is hungry again. He found one ant colony, consisting of n ants, ordered in a row. Each ant i (1 ≤ i ≤ n) has a strength si.In order to make his dinner more interesting, Mole organizes a version of «Hunger Games» for the ants. He chooses two numbers l and r (1 ≤ l ≤ r ≤ n) and each pair of ants with indices between l and r (inclusively) will fight. When two ants i and j fight, ant i gets one battle point only if si divides sj (also, ant j gets one battle point only if sj divides si).
After all fights have been finished, Mole makes the ranking. An ant i, with vi battle points obtained, is going to be freed only if vi = r - l, or in other words only if it took a point in every fight it participated. After that, Mole eats the rest of the ants. Note that there can be many ants freed or even none.
In order to choose the best sequence, Mole gives you t segments [li, ri] and asks for each of them how many ants is he going to eat if those ants fight.
Input
The first line contains one integer n (1 ≤ n ≤ 105), the size of the ant colony.
The second line contains n integers s1, s2, ..., sn (1 ≤ si ≤ 109), the strengths of the ants.
The third line contains one integer t (1 ≤ t ≤ 105), the number of test cases.
Each of the next t lines contains two integers li and ri (1 ≤ li ≤ ri ≤ n), describing one query.
Output
Print to the standard output t lines. The i-th line contains number of ants that Mole eats from the segment [li, ri].
Examples
input
5
1 3 2 4 2
4
1 5
2 5
3 5
4 5
output
4
4
1
1
Note
In the first test battle points for each ant are v = [4, 0, 2, 0, 2], so ant number 1 is freed. Mole eats the ants 2, 3, 4, 5.
In the second test case battle points are v = [0, 2, 0, 2], so no ant is freed and all of them are eaten by Mole.
In the third test case battle points are v = [2, 0, 2], so ants number 3 and 5 are freed. Mole eats only the ant 4.
In the fourth test case battle points are v = [0, 1], so ant number 5 is freed. Mole eats the ant 4.
题意:
给出n个数ai。T组询问l,r
对于每组询问[l,r] ,要求输出区间长度减去区间内能被所有区间内的数整除的个数(一个数能被整个区间整除)
思路:两个技巧,看了tourist真是好技巧
我的思路:线段树维护三个权值,一个区间gcd值,区间min值,区间min值出现的个数
然后对于每个询问,能被整个区间整除当然是区间最小值为区间的gcd值。减去最小值的个数就行了
代码:
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<string>#include<vector>#include <ctime>#include<queue>#include<set>#include<map>#include<stack>#include<iomanip>#include<cmath>#include<bitset>#define mst(ss,b) memset((ss),(b),sizeof(ss))///#pragma comment(linker, "/STACK:102400000,102400000")typedef long long ll;#define INF (1ll<<60)-1#define Max 1e10using namespace std;int n;int a[100100];int mn[500100],g[500100],num[500100];int gcd(int a,int b){ return b==0?a:gcd(b,a%b);}void pushup(int root){ g[root]=gcd(g[root*2],g[root*2+1]); if(mn[root*2]<mn[root*2+1]){ mn[root]=mn[root*2]; num[root]=num[root*2]; } else if(mn[root*2]>mn[root*2+1]){ mn[root]=mn[root*2+1]; num[root]=num[root*2+1]; } else if(mn[root*2]==mn[root*2+1]){ mn[root]=mn[root*2]; num[root]=num[root*2]+num[root*2+1]; }}void build(int root,int l,int r){ if(l==r){ num[root]=1; mn[root]=a[l]; g[root]=a[l]; return ; } int mid=(l+r)/2; build(root*2,l,mid); build(root*2+1,mid+1,r); pushup(root);}int query1(int root,int l,int r,int x,int y){ if(x<=l && y>=r){ return g[root]; } int mid=(l+r)/2; if(y<=mid) return query1(root*2,l,mid,x,y); else if(x>mid) return query1(root*2+1,mid+1,r,x,y); else { return gcd(query1(root*2,l,mid,x,mid),query1(root*2+1,mid+1,r,mid+1,y)); }}int Num,Mn;void query3(int root,int l,int r,int x,int y){ if(x<=l && y>=r){ if(Mn>mn[root]){ Mn=mn[root]; Num=num[root]; } else if(Mn==mn[root]){ Num+=num[root]; } return ; } int mid=(l+r)/2; if(x<=mid) query3(root*2,l,mid,x,y); if(y>mid) query3(root*2+1,mid+1,r,x,y);}int main(){ int T; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); build(1,1,n); scanf("%d",&T); while(T--){ int l,r; scanf("%d%d",&l,&r); int Gcd=query1(1,1,n,l,r); Num=0;Mn=Max; query3(1,1,n,l,r); ///printf("%d %d %d\n",Gcd,Mn,Num); if(Gcd==Mn){ printf("%d\n",r-l+1-Num); } else printf("%d\n",r-l+1); } return 0;}
接下来是tourist的:线段树维护区间的gcd值。
pair一个数组,当前第i个数对应的值为<ai,i>表示gcd值以及所在的位置编号。
然后排个序,这里的pair默认是先按第一个关键字排序。第一个关键字一样的话按第二个关键字排序
对于每组询问[l,r],已知区间的gcd值。
二分找出这个gcd值对应在pair里面的哪个位置,当pair里面的gcd出现多个的时候,找出第一个>=当前询问的l和r+1
分别为x和y
然后贡献就是r-l+1-(y-x)
代码:
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<string>#include<vector>#include <ctime>#include<queue>#include<set>#include<map>#include<stack>#include<iomanip>#include<cmath>#include<bitset>#define mst(ss,b) memset((ss),(b),sizeof(ss))///#pragma comment(linker, "/STACK:102400000,102400000")typedef long long ll;#define INF (1ll<<60)-1#define Max 1e10using namespace std;int n;int a[100100];int g[500100];int gcd(int a,int b){ return b==0?a:gcd(b,a%b);}void pushup(int root){ g[root]=gcd(g[root*2],g[root*2+1]);}void build(int root,int l,int r){ if(l==r){ g[root]=a[l]; return ; } int mid=(l+r)/2; build(root*2,l,mid); build(root*2+1,mid+1,r); pushup(root);}int query1(int root,int l,int r,int x,int y){ if(x<=l && y>=r){ return g[root]; } int mid=(l+r)/2; if(y<=mid) return query1(root*2,l,mid,x,y); else if(x>mid) return query1(root*2+1,mid+1,r,x,y); else { return gcd(query1(root*2,l,mid,x,mid),query1(root*2+1,mid+1,r,mid+1,y)); }}pair<int,int> p[100100];int main(){ int T; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); p[i]=make_pair(a[i],i); } sort(p+1,p+n+1); build(1,1,n); scanf("%d",&T); while(T--){ int l,r; scanf("%d%d",&l,&r); int Gcd=query1(1,1,n,l,r); int x=lower_bound(p+1,p+n+1,make_pair(Gcd,l))-p; int y=lower_bound(p+1,p+n+1,make_pair(Gcd,r+1))-p; printf("%d\n",r-l+1-(y-x)); } return 0;}
0 0
- Codeforces Round #271 (Div. 2) F 线段树+pair
- Codeforces Round #271 (Div. 2)F. Ant colony(线段树)
- Codeforces Round #271 (Div. 2) F. Ant colony(线段树)
- Codeforces Round #452 (Div. 2) F. Letters Removing 线段树
- Codeforces Round #271 (Div. 2) F题 Ant colony(线段树)
- Codeforces Round #271 (Div. 2) F题 Ant colony(线段树求区间gcd)
- Codeforces Round #271 (Div. 2) F - Ant colony 线段树 + GCD
- Codeforces Round #209 (Div. 2)-C. Prime Number(set)和D. Pair of Numbers(线段树)
- Educational Codeforces Round 33 (Rated for Div. 2) F. Subtree Minimum Query (线段树)
- 线段树Codeforces Round #136 (Div. 2)
- Codeforces Round #271 (Div. 2) E 离散化+线段树
- Codeforces Round #397 F Souvenirs(线段树)
- Codeforces Round #394 (Div. 2) F. Dasha and Photos(二位前缀和+线段树/二维前缀和,好题)
- Codeforces Round #271 (Div. 2) F Ant colony
- 【Codeforces Round 271 (Div 2)F】【贪心 线段树】Ant colony 区间段内是其他所有数因子的数的个数
- Codeforces Round #277.5 (Div. 2) F
- Codeforces Round #279 (Div. 2) F
- Codeforces Round #279 (Div. 2) F
- ROS(indigo)一个简单灵活和可扩展的2D多机器人仿真器stdr_simulator
- SGU326 perspective 最大流 竞赛排名问题
- python3 比较两个list的结构
- poj 1860 Currency Exchange
- Android应用优化过程分析
- Codeforces Round #271 (Div. 2) F 线段树+pair
- 红黑树(插入)
- [2016ACM多校] HDU5768 容斥原理 中国剩余定理
- 完全卸载oracle11g教程、Oracle11g的卸载方法和步骤
- 风靡的七个人生工具(SWOT、PDCA、6W2H、SMART、WBS、时间管理、二八原则)
- PAT 1051. Pop Sequence
- hdu 1080 Human Gene Functions( 类似最长公共子序列)
- 【POJ2155】Matrix-二维树状数组+前缀和
- 20160729 其他小代码