problem

给定一个长度为 nnn 的排列 aaa。有 qqq 个询问,每次询问一个区间 [l,r][l,r][l,r]。求这个区间的 kkk 值。

其中 k=∑i=lr∑j=i+1rf(ai,aj),f(x,y)k=\sum_{i=l}^r\sum_{j=i+1}^rf(a_i,a_j),f(x,y)k=∑i=lr​∑j=i+1r​f(ai​,aj​),f(x,y) 为一个递归函数,定义如下:

  • 当 x=yx=yx=y,其值为 111。
  • 当 n≠yn\ne yn​=y,其值为 f(x+y+∣x−y∣,∣x−y∣)f(x+y+|x-y|,|x-y|)f(x+y+∣x−y∣,∣x−y∣)。
  • 若无限循环,其值为 000。

n,q≤1e5n,q\le 1e5n,q≤1e5。

solution

observation1:\text{observation1}:observation1: 首先观察这个函数,不难发现这个函数 x,yx,yx,y 的和是不变的。

所以当这个和为奇数的时候,一定会死循环,不可能走到 x=yx=yx=y 的局面。

否则 x,yx,yx,y 一定同奇偶。

observation2:\text{observation2}:observation2: 又不难知道加减运算过程中结果仍是 gcd\text{gcd}gcd 的倍数。所以去掉不影响答案。

因此我们可以将 x,yx,yx,y 都除以他们的 gcd\text{gcd}gcd。那么此时得到的 x,yx,yx,y 均为奇数且互质。


接下来假设 x>yx>yx>y,我们可以同时除以他们的 gcd\text{gcd}gcd。

由于 x,yx,yx,y 同为奇,故 y∗2,x−yy*2,x-yy∗2,x−y 都是偶数。

再假设 y∗2,x−yy*2,x-yy∗2,x−y 有与 222 互质的公因数 k(k≠1)k(k\ne 1)k(k​=1)。

则 k∣y∧k∣x−yk\mid y\wedge k\mid x-yk∣y∧k∣x−y,所以 k∣xk\mid xk∣x,这与 (x,y)=1(x,y)=1(x,y)=1 矛盾。

所以这个 gcd\text{gcd}gcd 一定为 222。

所以 f(x,y)f(x,y)f(x,y) 等价于 f(x−y2,y)f(\frac{x-y}{2},y)f(2x−y​,y)。

故其和每次都会除以 222,直到 x=y=1x=y=1x=y=1 或死循环。

这样我们就可以求出 f(i,j)f(i,j)f(i,j) 的值为 g(i+jgcd⁡(i,j))g(\frac{i+j}{\gcd(i,j)})g(gcd(i,j)i+j​),其中当 x=2kx=2^kx=2k 时,g(x)=kg(x)=kg(x)=k;否则 g(k)=0g(k)=0g(k)=0。


假设 x,yx,yx,y 最简比为 a,ba,ba,b,即 xa=yb\frac xa=\frac ybax​=by​。

我们不妨枚举 2i2^i2i,使得 a+b=2ia+b=2^ia+b=2i,然后枚举 aaa,自然就知道了 bbb。还需要检查一下 a,ba,ba,b 互质。

再枚举这个比例,进而也能知道 x,yx,yx,y。

显然这样的 (a,b)(a,b)(a,b) 有 2i2^i2i 种,且 xa=yb=d≤n2i−1\frac xa=\frac yb=d\le \frac{n}{2^{i-1}}ax​=by​=d≤2i−1n​。

这样合法的不同的 (x,y)(x,y)(x,y) 只有 2n2n2n 对左右。

一共也就 O(nlog⁡n)O(n\log n)O(nlogn) 的级别,我们完全可以将这些二元组记下来,问题就转换成了二维偏序问题。

就可以用树状数组做了。

时间复杂度 O(nlog⁡2n)O(n\log^2n)O(nlog2n)。

其实由二离和分块的做法,但我不会哈哈哈

code

#include <bits/stdc++.h>
using namespace std;
#define maxn 200005
#define int long long
int n, m;
int a[maxn], p[maxn], ret[maxn], t[maxn];
vector < int > G[maxn];
vector < pair < int, int > > Q[maxn];int gcd( int x, int y ) {if( ! y ) return x;else return gcd( y, x % y );
}void add( int i, int x ) {for( ;i <= n;i += i & -i ) t[i] += x;
}int ask( int i ) {int ans = 0;\for( ;i;i -= i & -i ) ans += t[i];return ans;
}int F( int x, int y ) {if( x == y ) return 1;if( x < y ) swap( x, y );return F( y << 1, x - y ) + 1;
}void solve() {for( int i = 1;i <= n;i ++ ) {for( int j : G[i] ) {int k = F( a[j], a[i] );add( 1, k ), add( j + 1, -k );}for( auto j : Q[i] ) ret[j.second] = ask( j.first );}
}signed main() {scanf( "%lld", &n );for( int i = 1;i <= n;i ++ ) scanf( "%lld", &a[i] ), p[a[i]] = i;for( int i = 0;(1 << i) <= (n << 1);i ++ ) {for( int j = 1;j <= n;j ++ ) {int k = (1 << i) - a[j];if( k <= 0 or k > n or p[k] > j or a[j] == k ) continue;if( gcd( k, a[j] ) ^ 1 ) continue;for( int o = 1;p[o * k] and p[o * a[j]];o ++ ) {int x = p[o * k], y = p[o * a[j]];if( x > y ) swap( x, y );G[y].push_back( x );}}}scanf( "%lld", &m );for( int i = 1, l, r;i <= m;i ++ ) {scanf( "%lld %lld", &l, &r );Q[r].push_back( make_pair( l, i ) );}solve();for( int i = 1;i <= m;i ++ ) printf( "%lld\n", ret[i] );return 0;
}

Function Query(树状数组)相关推荐

  1. HDU 5869 Different GCD Subarray Query 树状数组 + 一些数学背景

    http://acm.hdu.edu.cn/showproblem.php?pid=5869 题意:给定一个数组,然后给出若干个询问,询问[L, R]中,有多少个子数组的gcd是不同的. 就是[L, ...

  2. 树状数组 区间update/query

    Re [问题引入] 对于区间修改.区间查询这样的简单问题,打一大堆线段树确实是不划算,今天来介绍一下区间查询+区间修改的树状数组 [一些基础] 树状数组的基本知识不再介绍,请自行百度 我们假设sigm ...

  3. 2016 大连网赛---Different GCD Subarray Query(GCD离散+树状数组)

    题目链接 http://acm.split.hdu.edu.cn/showproblem.php?pid=5869 Problem Description This is a simple probl ...

  4. 【HDU - 5869】Different GCD Subarray Query(思维,数学,gcd,离线处理,查询区间不同数,树状数组 或 二分RMQ)

    题干: This is a simple problem. The teacher gives Bob a list of problems about GCD (Greatest Common Di ...

  5. hdu 4836 The Query on the Tree(线段树or树状数组)

    The Query on the Tree Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Ot ...

  6. 2017 ACM-ICPC乌鲁木齐网络赛 G. Query on a string(KMP+树状数组)

    题目链接:https://www.jisuanke.com/contest/870 题意: 给出两个字符串S和T,Q次操作:①C a b表示将第a个字符改为b:②Q l r表示T在S的子串[l, r] ...

  7. 树状数组 + 二分 - Query HDU - 4339

    树状数组 + 二分 - Query HDU - 4339 题意: T组测试用例,每组给定两个长度分别为l1和l2的字符串s1,s2.有两种询问:①.1idic:将第id个字符串的第i个字符变成字符c. ...

  8. LeetCode Range Sum Query - Mutable(树状数组、线段树)

    问题:给出一个整数数组,求出数组从索引i到j范围内元素的总和.update(i,val)将下标i的数值更新为val 思路:第一种方式是直接根据定义,计算总和时直接计算从i到j的和 第二种方式是使用树状 ...

  9. hdu4339 Query (字符串公共长度,树状数组+二分)

    题意: 给两个字符串s1,s2(长度可能不同) 和m次操作 操作有两种: (1 a i c)表示把第a个字符串的第i个字符改成字符c (其中a为1或者2) (2 i)输出最大的j,满足两个字符串在区间 ...

最新文章

  1. 为自己搭建一个鹊桥 -- Native Page与Web View之间的JSBridge实现方式
  2. python中PIL模块
  3. Linux网络DNS分离解析
  4. c 导入数据到oracle,excel中数据导入到Orcale数据库表中的方法 | 学步园
  5. okta-spring_通过Okta的单点登录保护Spring Boot Web App的安全
  6. 喷水装置(信息学奥赛一本通-T1424)
  7. 华为c语言中static的作用,C语言编程规范(华为、林锐、MISRAC).pdf
  8. ECS服务器下挂载数据盘
  9. android (12) Fragment使用
  10. perl 脚本学习-----两个文件排序之后输入到一个文件
  11. 新系统基础优化--Centos6.6
  12. 智驾科技MAXIEYE完成3亿元B轮融资,暂未取得品牌同名商标
  13. 你还发现了CSDN那些变化
  14. 抓包工具Charles乱码解决办法
  15. MySQL导出记录到Excel表格下载打开后乱码问题
  16. word根据数字符号自动回车
  17. 使用屏幕录制专家--录制视频技巧
  18. Linux系统漏洞本地提权
  19. 速卖通开店入驻收费:各类目费用一览表及开店入驻绿色通道
  20. 串口通信,接收并解析数据的方式

热门文章

  1. 一招搞定高等数学! | 今日最佳
  2. Java并发编程实战_真香!阿里P8耗时半年著作660页Java高并发与网络编程实战总结...
  3. mysql怎么查看索引情况_mysql 查看索引使用情况
  4. python双除_python2和python3 中的除法的区别
  5. 早教机器人刷固件_机器人线刷包_机器人刷机包_机器人固件包_机器人救砖包 - 线刷宝ROM中心...
  6. dma接收双缓存 stm32_「STM32学习笔记」USART 新特性
  7. python 中文编码差异_Python 编码为什么那么蛋疼?
  8. 如何在注册表里计算机用户名,可以通过注册表修改电脑的密码 ?怎么做的?
  9. python如何封装成可调用的库_Python实现打包成库供别的模块调用
  10. realloc函_[转载]realloc函数的使用及注意事项(转)