hdu5381The sum of gcd 线段树+set
来源:互联网 发布:美亚海淘宝宝用品清单 编辑:程序博客网 时间:2024/06/05 11:47
//f(l,r)=∑(i=l~r)∑j=(i~r)gcd(ai,ai+1....aj)//可以知道每添加一个新的数i,添加了i个区间//而确定了右端点的所有数最多有log(a[i])个//因为从右往前走,每次最少除2//所以可以先将其离线//然后从前到后加入ai用set存入以i为最后一个区间的所有区间//中所有不同的gcd,每个gcd的个数//然后用线段树进行成段的更新#include<cstdio>#include<string>#include<iostream>#include<vector>#include<set>using namespace std ;#define left v<<1#define right v<<1|1const int maxn = 1e4+10 ;typedef long long ll ;vector<pair<int , int> >vec[maxn] ;ll ans[maxn] ;int a[maxn] ;int gcd(int a , int b){ if(b==0)return a ; return gcd(b , a%b) ;};struct T{ int l , r ; ll va ; ll la ;}tree[maxn<<2];void push_down(int v){ if(tree[v].la) { ll tmp = tree[v].la ; tree[left].va += tmp*(tree[left].r - tree[left].l + 1) ; tree[right].va += tmp*(tree[right].r - tree[right].l + 1) ; tree[left].la += tmp ; tree[right].la += tmp ; tree[v].la = 0 ; }}void push_up(int v){ tree[v].va = tree[left].va + tree[right].va ;}void build(int l , int r , int v){ tree[v].l = l ; tree[v].r = r ; tree[v].la = 0 ; if(l == r) { tree[v].va = 0 ; return ; } int mid = (l + r) >> 1 ; build(l , mid , left) ; build(mid+1 , r , right) ;}void update(int l , int r , int v , ll c){ if(l <= tree[v].l && tree[v].r <= r) { tree[v].va += c*(tree[v].r - tree[v].l + 1) ; tree[v].la += c ; return ; } push_down(v) ; int mid = (tree[v].l + tree[v].r) >> 1 ; if(l <= mid) update(l , r , left , c) ; if(r > mid) update(l , r , right , c) ; push_up(v) ;}ll query(int l , int r , int v){ if(l <= tree[v].l && tree[v].r <= r) return tree[v].va ; push_down(v) ; int mid = (tree[v].l + tree[v].r) >> 1 ; ll ans = 0 ; if(l <= mid)ans += query(l , r , left) ; if(r > mid)ans += query(l , r , right) ; push_up(v) ; return ans ;}int main(){ //freopen("d:\\in.txt" , "r" , stdin) ; int t ; scanf("%d" , &t) ; while(t--) { int n ; scanf("%d" , &n) ; for(int i = 1;i <= n;i++) { scanf("%d" , &a[i]) ; vec[i].clear() ; } int q ; scanf("%d" , &q) ; for(int i = 1;i <= q;i++) { int l , r ; scanf("%d%d" , &l , &r) ; vec[r].push_back(make_pair(l , i)) ; } set<pair<int , int> >::iterator it ; set<pair<int , int> > se[2] ; se[0].clear() ;se[1].clear() ; build(1 , n , 1) ; for(int i = 1;i <= n;i++) { int sum = 0 ; int pos = -1 ; int l = 1 ; se[(i+1)%2].clear() ; for(it = se[i%2].begin() ;it != se[i%2].end();it++) { int tmp = gcd(it->first , a[i]) ; if(pos == -1 || tmp == pos){ pos = tmp ; sum += it->second ; } else { se[(i+1)%2].insert(make_pair(pos , sum)) ; update(l , l + sum -1 , 1 , pos) ; l += sum ; pos = tmp ; sum = it->second ; } } if(pos == -1) { update(1 , 1 , 1 , a[i]) ; se[(i+1)%2].insert(make_pair(a[i] , 1)) ; } else if(pos == a[i]) { update(l , l+sum , 1 , pos) ; se[(i+1)%2].insert(make_pair(pos , sum+1)) ; } else { update(l , l + sum - 1 , 1 , pos) ; se[(i+1)%2].insert(make_pair(pos , sum)) ; update(l+sum , l+sum , 1 , a[i]) ; se[(i+1)%2].insert(make_pair(a[i] , 1)) ; } for(int j = 0;j < vec[i].size();j++) ans[vec[i][j].second] = query(vec[i][j].first , i,1) ; } for(int i = 1;i <= q;i++) printf("%lld\n" , ans[i]) ; } return 0 ;}
0 0
- hdu5381The sum of gcd 线段树+set
- hdu5381The sum of gcd
- hdu 5381 The sum of gcd(线段树+gcd)
- 【线段树】 HDOJ 5381 The sum of gcd
- HDU 5381 The sum of gcd 离线处理+线段树
- hdu 5381 The sum of gcd(线段树)
- hdu 5381 The sum of gcd(线段树等差数列区间修改+单点查询)
- hdu5381(2015多校8)--The sum of gcd(线段树)
- HDU4676 Sum Of Gcd
- Sum Of Gcd
- hdu4676 Sum Of Gcd
- Sum Of Gcd HDU
- hdu 5381 The sum of gcd (线段树x树状数组x区间和维护进阶x离线处理)
- HDU5381-The sum of gcd
- hdu5930 GCD线段树
- HDU 5381 The sum of gcd
- hdu 5381 The sum of gcd
- hdu 5381 The sum of gcd
- DevExpress VCL for C++BUILDER XE6
- 关于1ul 1l 1u 的理解也许有不对的
- dos中如何编译机器码
- 我想要个好看的404,哈哈
- Android适配全攻略
- hdu5381The sum of gcd 线段树+set
- net.sf.hibernate.MappingException
- ZOJ 3635 Cinema in Akiba【线段树】
- maven之Nexus的配置【pom.xml配置<repositories>】(五)
- C#与Java基础语法初比较
- 字符串压缩
- 深入理解iOS API系列(四)理解CNContactPickerDelegate
- net.sf.hibernate.PropertyNotFoundExceptio
- 【二叉树】关于二叉树的后续遍历遍历以及栈