HDU5869 Different GCD Subarray Query(线段树&&离线处理)
2016-09-10 19:25
288 查看
题目:
http://acm.split.hdu.edu.cn/showproblem.php?pid=5869
题意:
找区间内所有子串GCD的个数思路:
线段树离线搞搞,区间GCD收敛的很快,所以直接暴力预处理出到每个数字截至的后缀串有哪些GCD以及它们的位置,就是每个数字向前看有哪些GCD出现,这个数量是很少的。扫一遍然后离线询问,对于每个询问按照右端点排序。找到每个位置的时候把这个位置向前看的所有GCD的位置更新到pos[]里,pos[]存的就是每个gcd最后出现的位置,然后对于右端点在当前位置的询问线段树找一下pos[]在这个区间内的和就是答案了。代码:
//kopyh #include <bits/stdc++.h> #define INF 0x3f3f3f3f #define MOD 1000000007 #define N 112345 using namespace std; int n,m,sum,res,flag; #define root 1 , n , 1 #define lson l , m , rt << 1 #define rson m + 1 , r , rt << 1 | 1 struct node { int pos,val; node(int x=0,int y=0){pos=x,val=y;} friend bool operator < (node a, node b) { return a.val < b.val; } friend node operator + (node a, node b) { return node(a.pos,a.val+b.val); } }arr[N<<2]; int add[N<<2],tot; void pushUp(int rt) { arr[rt] = arr[rt<<1]+arr[rt<<1|1]; } void pushDown(int l,int r,int rt) { if(add[rt]) { int m = (l+r)>>1; add[rt<<1] += add[rt]; add[rt<<1|1] += add[rt]; arr[rt<<1].val += (m-l+1)*add[rt]; arr[rt<<1|1].val += (r-m)*add[rt]; add[rt] = 0; } } void updata(int l,int r,int rt,int ql,int qr,int val) { if(l>qr||ql>r)return; if(l>=ql&&r<=qr) { arr[rt].val += (r-l+1)*val; add[rt] += val; return; } pushDown(l,r,rt); int m = (l+r)>>1; if(ql<=m)updata(lson,ql,qr,val); if(qr>m)updata(rson,ql,qr,val); pushUp(rt); } void build(int l,int r,int rt) { add[rt]=0; if(l == r) { arr[rt].val = 0; arr[rt].pos = tot; return; } int m = (l+r)>>1; build(lson); build(rson); pushUp(rt); } node query(int l,int r,int rt,int ql,int qr) { if(l>qr||ql>r) return node(0,0); if(l>=ql&&r<=qr) return arr[rt]; pushDown(l,r,rt); int m = (l+r)>>1; return query(lson,ql,qr)+query(rson,ql,qr); } int a ,pos[N*10],ans ; vector<pair<int,int> >vc ,qu ; int gcd(int x,int y) { return y?gcd(y,x%y):x; } int main() { #ifndef ONLINE_JUDGE freopen("test.txt","r",stdin); #endif int i,j,k,cas,T,t,x,y,z,now; while(scanf("%d%d",&n,&m)!=EOF) { for(i=1;i<=n;i++) { scanf("%d",&a[i]); vc[i].clear(); qu[i].clear(); } for(i=1;i<=n;i++) { x=a[i]; y=i; for(j=0;j<vc[i-1].size();j++) { t = gcd(vc[i-1][j].first,a[i]); if(t!=x) { vc[i].push_back(make_pair(x,y)); x=t; y=vc[i-1][j].second; } } vc[i].push_back(make_pair(x,y)); } for(i=1;i<=m;i++) { scanf("%d%d",&x,&y); qu[y].push_back(make_pair(x,i)); } memset(pos,0,sizeof(pos)); build(root); for(i=1;i<=n;i++) { for(j=0;j<vc[i].size();j++) if(pos[vc[i][j].first] < vc[i][j].second) { if(pos[vc[i][j].first])updata(root,pos[vc[i][j].first],pos[vc[i][j].first],-1); updata(root,vc[i][j].second,vc[i][j].second,1); pos[vc[i][j].first] = vc[i][j].second; // printf("pos=%d %d\n",vc[i][j].first,pos[vc[i][j].first]); } for(j=0;j<qu[i].size();j++) ans[qu[i][j].second] = query(root,qu[i][j].first,i).val; } for(i=1;i<=m;i++) printf("%d\n",ans[i]); } return 0; }
相关文章推荐
- ZOJ:3633 Alice's present(离线处理)
- SPOJ D-query && HDU 3333 Turing Tree (线段树 && 区间不相同数个数or和 && 离线处理)
- HDU 4288 && Codeforces 85D (线段树+离散化+离线处理)
- Codeforces-707D:Persistent Bookcase (离线处理特殊的可持久化问题&&Bitset)
- hdu2586&&poj1330 求点间最短距&&最近公共祖先(在线&&离线处理):::可做模板
- hdu 4791 Alice's Print Service (DP+离线处理)
- 在SQL中参数值超过8000(TEXT类型)的处理方法,以"逗号"分隔的字符串
- Javascript & DOM 中de表单处理
- "传奇杀手"病毒的处理方法
- 7-23错误处理&数据缓存
- ora-12154 TNS:"无法处理服务名"的一个解决方法(转)
- myEclipse错误处理--An internal error occurred during: "Generating Artifacts".
- 用Delphi7编写代码时出现"dcc70.dll"调用失败的处理方法
- 新闻标题超出一定长度显示"..."的CSS处理方法
- 关于JSP中URL传值特殊字符的处理(如#,&)
- extern "C"处理C代码
- MPEG4 & H.264学习笔记之三 ------ 图像模型(图像处理过程)
- ASP & VBScript的错误处理
- 一个用于处理分隔","的函数tf_split_str
- C#"焦点事件"中的Validating处理方法