Different GCD Subarray Query HDU - 5869 (gcd处理+离线线段树·)
2017-08-25 13:16
357 查看
题意:
找l~r区间不同gcd个数
思路:
第二次做这题了。又卡住了。
离线线段树部分就是让新的gcd尽可能的向右更新。但是感觉主要的问题是在于gcd的处理,对于每个gcd的起点,需要记录一下。而且也需要再处理的时候保证没有重复的gcd,且这个gcd的位置尽可能的靠右。
做法是把gcd从大到小放进去,之后再逐次取出,只有当不等时,才更新位置和值
找l~r区间不同gcd个数
思路:
第二次做这题了。又卡住了。
离线线段树部分就是让新的gcd尽可能的向右更新。但是感觉主要的问题是在于gcd的处理,对于每个gcd的起点,需要记录一下。而且也需要再处理的时候保证没有重复的gcd,且这个gcd的位置尽可能的靠右。
做法是把gcd从大到小放进去,之后再逐次取出,只有当不等时,才更新位置和值
#include <algorithm> #include <iostream> #include <cstdlib> #include <cstdio> #include <cstring> #include <vector> #include <map> #define ll long long using namespace std; const int N=1000005; vector<pair<int,int> > vec ; int a ; int gcd(int x,int y) { if(x<y)swap(x,y); return y==0?x:gcd(y,x%y); } int pos ; int n,m; struct node { int l,r,id; bool friend operator<(node x,node y) { return x.r<y.r; } } b ; int ans ; struct nodetree { int sum; } tree[N*4]; void build(int i,int l,int r) { tree[i].sum=0; if(l==r) return ; int mid=(l+r)>>1; build(i<<1,l,mid); build(i<<1|1,mid+1,r); } int query(int i,int left,int right,int nl,int nr) { if(left==nl&&right==nr) return tree[i].sum; int mid=(left+right)>>1; int res=0; if(nr<=mid) res+=query(i<<1,left,mid,nl,nr); else if(nl>mid) res+=query(i<<1|1,mid+1,right,nl,nr); else { res+=query(i<<1,left,mid,nl,mid); res+=query(i<<1|1,mid+1,right,mid+1,nr); } return res; } void update(int i,int left,int right ,int pos,int val) { if(left==right&&right==pos) { tree[i].sum+=val; return ; } int mid=(lef 4000 t+right)>>1; if(pos<=mid) update(i<<1,left,mid,pos,val); else update(i<<1|1,mid+1,right,pos,val); tree[i].sum=tree[i<<1].sum+tree[i<<1|1].sum; return ; } int main() { while(~scanf("%d%d",&n,&m)) { for(int i=1; i<=n; i++) scanf("%d",&a[i]); for(int i=1; i<=m; i++) { scanf("%d%d",&b[i].l,&b[i].r); b[i].id=i; } for(int i=1; i<=n; i++) vec[i].clear(); vec[1].push_back(make_pair(a[1],1)); for(int i=2; i<=n; i++) { int pre=a[i]; int posi=i; for(int j=0; j<vec[i-1].size(); j++) { int num=gcd(pre,vec[i-1][j].first); if(num!=pre) vec[i].push_back(make_pair(pre,posi)) ,posi=vec[i-1][j].second,pre=num; } vec[i].push_back(make_pair(pre,posi)); }/* for(int i=1; i<=n; i++) { for(int j=0; j<vec[i].size(); j++) printf(" --%d %d-- ",vec[i][j].first,vec[i][j].second); printf("\n"); }*/ sort(b+1,b+1+m); build(1,1,n); int now=1; memset(pos,0,sizeof(pos)); for(int i=1; i<=n; i++) { for(int j=0; j<vec[i].size(); j++) { int nm=vec[i][j].first,posi=vec[i][j].second; if(pos[nm]<posi) { if(pos[nm]) { update(1,1,n,pos[nm],-1); } update(1,1,n,posi,1); pos[nm]=posi; } } while(b[now].r==i) { int res=query(1,1,n,b[now].l,b[now].r); ans[b[now].id]=res; now++; } } for(int i=1; i<=m; i++) { printf("%d\n",ans[i]); } } return 0; }
相关文章推荐
- HDU 5869 Different GCD Subarray Query (离线处理 树状数组)
- HDU 5869 Different GCD Subarray Query(离线处理+树状数组)
- HDU - 5869 Different GCD Subarray Query 树状数组离线处理
- [区间GCD预处理 树状数组 离线] HDU 5869 Different GCD Subarray Query
- HDU5869 Different GCD Subarray Query(离线线段树)
- Different GCD Subarray Query (离线的处理)
- HDU 5869 Different GCD Subarray Query(离线+gcd)
- HDU 5869 Different GCD Subarray Query (数学gcd+树状数组离线查询)
- HDU 5869 Different GCD Subarray Query 离线 树状数组
- [HDOJ5869] Different GCD Subarray Query(RMQ,树状数组,离线)
- hdu 5869 Different GCD Subarray Query 预处理 + 离线
- hdu 5869 Different GCD Subarray Query 离线+树状数组
- HDU 5869 Different GCD Subarray Query 离线+树状数组
- hdu-5869 Different GCD Subarray Query gcd预处理 + 树状数组 + 离线
- HDU 5869 Different GCD Subarray Query [区间gcd预处理+离线]【数据结构】
- [HDU 5869] Different GCD Subarray Query (线段树GCD+离线算法) (好题)
- HDU 5869 Different GCD Subarray Query (GCD种类预处理+树状数组维护)
- 【2016-大连赛区网络赛-B】树状数组(Different GCD Subarray Query,hdu 5869)
- HDU 5869 Different GCD Subarray Query
- HDU 4630 gcd(线段树离线处理)