日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Function Query(树状数组)

發(fā)布時(shí)間:2023/12/3 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Function Query(树状数组) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

problem

給定一個(gè)長(zhǎng)度為 nnn 的排列 aaa。有 qqq 個(gè)詢問(wèn),每次詢問(wèn)一個(gè)區(qū)間 [l,r][l,r][l,r]。求這個(gè)區(qū)間的 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) 為一個(gè)遞歸函數(shù),定義如下:

  • 當(dāng) x=yx=yx=y,其值為 111
  • 當(dāng) 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)
  • 若無(wú)限循環(huán),其值為 000

n,q≤1e5n,q\le 1e5n,q1e5

solution

observation1:\text{observation1}:observation1: 首先觀察這個(gè)函數(shù),不難發(fā)現(xiàn)這個(gè)函數(shù) x,yx,yx,y 的和是不變的。

所以當(dāng)這個(gè)和為奇數(shù)的時(shí)候,一定會(huì)死循環(huán),不可能走到 x=yx=yx=y 的局面。

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

observation2:\text{observation2}:observation2: 又不難知道加減運(yùn)算過(guò)程中結(jié)果仍是 gcd\text{gcd}gcd 的倍數(shù)。所以去掉不影響答案。

因此我們可以將 x,yx,yx,y 都除以他們的 gcd\text{gcd}gcd。那么此時(shí)得到的 x,yx,yx,y 均為奇數(shù)且互質(zhì)。


接下來(lái)假設(shè) x>yx>yx>y,我們可以同時(shí)除以他們的 gcd\text{gcd}gcd

由于 x,yx,yx,y 同為奇,故 y?2,x?yy*2,x-yy?2,x?y 都是偶數(shù)。

再假設(shè) y?2,x?yy*2,x-yy?2,x?y 有與 222 互質(zhì)的公因數(shù) k(k≠1)k(k\ne 1)k(k?=1)

k∣y∧k∣x?yk\mid y\wedge k\mid x-ykykx?y,所以 k∣xk\mid xkx,這與 (x,y)=1(x,y)=1(x,y)=1 矛盾。

所以這個(gè) gcd\text{gcd}gcd 一定為 222

所以 f(x,y)f(x,y)f(x,y) 等價(jià)于 f(x?y2,y)f(\frac{x-y}{2},y)f(2x?y?,y)

故其和每次都會(huì)除以 222,直到 x=y=1x=y=1x=y=1 或死循環(huán)。

這樣我們就可以求出 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?),其中當(dāng) x=2kx=2^kx=2k 時(shí),g(x)=kg(x)=kg(x)=k;否則 g(k)=0g(k)=0g(k)=0


假設(shè) x,yx,yx,y 最簡(jiǎn)比為 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 互質(zhì)。

再枚舉這個(gè)比例,進(jìn)而也能知道 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?=d2i?1n?

這樣合法的不同的 (x,y)(x,y)(x,y) 只有 2n2n2n 對(duì)左右。

一共也就 O(nlog?n)O(n\log n)O(nlogn) 的級(jí)別,我們完全可以將這些二元組記下來(lái),問(wèn)題就轉(zhuǎn)換成了二維偏序問(wèn)題。

就可以用樹(shù)狀數(shù)組做了。

時(shí)間復(fù)雜度 O(nlog?2n)O(n\log^2n)O(nlog2n)

其實(shí)由二離和分塊的做法,但我不會(huì)哈哈哈

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; }

總結(jié)

以上是生活随笔為你收集整理的Function Query(树状数组)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。