Function Query(树状数组)
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+1rf(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(nlogn)O(n\log n)O(nlogn) 的级别,我们完全可以将这些二元组记下来,问题就转换成了二维偏序问题。
就可以用树状数组做了。
时间复杂度 O(nlog2n)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(树状数组)相关推荐
- HDU 5869 Different GCD Subarray Query 树状数组 + 一些数学背景
http://acm.hdu.edu.cn/showproblem.php?pid=5869 题意:给定一个数组,然后给出若干个询问,询问[L, R]中,有多少个子数组的gcd是不同的. 就是[L, ...
- 树状数组 区间update/query
Re [问题引入] 对于区间修改.区间查询这样的简单问题,打一大堆线段树确实是不划算,今天来介绍一下区间查询+区间修改的树状数组 [一些基础] 树状数组的基本知识不再介绍,请自行百度 我们假设sigm ...
- 2016 大连网赛---Different GCD Subarray Query(GCD离散+树状数组)
题目链接 http://acm.split.hdu.edu.cn/showproblem.php?pid=5869 Problem Description This is a simple probl ...
- 【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 ...
- 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 ...
- 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] ...
- 树状数组 + 二分 - Query HDU - 4339
树状数组 + 二分 - Query HDU - 4339 题意: T组测试用例,每组给定两个长度分别为l1和l2的字符串s1,s2.有两种询问:①.1idic:将第id个字符串的第i个字符变成字符c. ...
- LeetCode Range Sum Query - Mutable(树状数组、线段树)
问题:给出一个整数数组,求出数组从索引i到j范围内元素的总和.update(i,val)将下标i的数值更新为val 思路:第一种方式是直接根据定义,计算总和时直接计算从i到j的和 第二种方式是使用树状 ...
- hdu4339 Query (字符串公共长度,树状数组+二分)
题意: 给两个字符串s1,s2(长度可能不同) 和m次操作 操作有两种: (1 a i c)表示把第a个字符串的第i个字符改成字符c (其中a为1或者2) (2 i)输出最大的j,满足两个字符串在区间 ...
最新文章
- 为自己搭建一个鹊桥 -- Native Page与Web View之间的JSBridge实现方式
- python中PIL模块
- Linux网络DNS分离解析
- c 导入数据到oracle,excel中数据导入到Orcale数据库表中的方法 | 学步园
- okta-spring_通过Okta的单点登录保护Spring Boot Web App的安全
- 喷水装置(信息学奥赛一本通-T1424)
- 华为c语言中static的作用,C语言编程规范(华为、林锐、MISRAC).pdf
- ECS服务器下挂载数据盘
- android (12) Fragment使用
- perl 脚本学习-----两个文件排序之后输入到一个文件
- 新系统基础优化--Centos6.6
- 智驾科技MAXIEYE完成3亿元B轮融资,暂未取得品牌同名商标
- 你还发现了CSDN那些变化
- 抓包工具Charles乱码解决办法
- MySQL导出记录到Excel表格下载打开后乱码问题
- word根据数字符号自动回车
- 使用屏幕录制专家--录制视频技巧
- Linux系统漏洞本地提权
- 速卖通开店入驻收费:各类目费用一览表及开店入驻绿色通道
- 串口通信,接收并解析数据的方式
热门文章
- 一招搞定高等数学! | 今日最佳
- Java并发编程实战_真香!阿里P8耗时半年著作660页Java高并发与网络编程实战总结...
- mysql怎么查看索引情况_mysql 查看索引使用情况
- python双除_python2和python3 中的除法的区别
- 早教机器人刷固件_机器人线刷包_机器人刷机包_机器人固件包_机器人救砖包 - 线刷宝ROM中心...
- dma接收双缓存 stm32_「STM32学习笔记」USART 新特性
- python 中文编码差异_Python 编码为什么那么蛋疼?
- 如何在注册表里计算机用户名,可以通过注册表修改电脑的密码 ?怎么做的?
- python如何封装成可调用的库_Python实现打包成库供别的模块调用
- realloc函_[转载]realloc函数的使用及注意事项(转)