题目大意:给一个序列,每次换一个位置的值,求每次更新后任意连续的序列的gcd,有几个不同的。序列长度和数字大小<=10W 修改5w次
题解:一开始求出整个每个不同gcd的值可以出现多少次,更新的话对左端所有相同gcd的段求出来,和右端的的段直接暴力更新,由于两端都最多只有logn段,所以复杂度是可以承受的。
#include
using namespace std ;
#define maxn 51000
#define maxm 1100000
#define pii pair < int , int >
#define ft first
#define sd second
#define clr( a , x ) memset ( a , x , sizeof a )
#define root 1,1 ,n
#define ls rt<<1
#define rs rt<<1|1
#define lson ls,l,m
#define rson rs,m+1,r
int n , q ;
int a[maxn] ;
int vis[maxm] ;
int val[maxn<<2] ;
vector G[2] ;
int ans ;
int gcd(int x,int y)
{
if(x> 1 ;
if ( x <= m ) update ( x , v , lson ) ;
else update ( x , v , rson ) ;
val[rt] = gcd ( val[ls] , val[rs] ) ;
}
int query ( int L , int R , int rt , int l , int r ) {
if ( L <= l && r <= R ) return val[rt] ;
int m = l + r >> 1 ;
if ( R <= m ) return query ( L , R , lson ) ;
if ( m < L ) return query ( L , R , rson ) ;
return gcd ( query ( L , R , lson ) , query ( L , R , rson ) ) ;
}
pii queryl ( int R , int v , int rt , int l , int r ) {
if ( r <= R )
{
if ( val[rt] % v == 0 ) return pii ( v , l ) ;
else if ( l == r ) return pii ( gcd ( v , val[rt] ) , l ) ;
}
int m = l + r >> 1 ;
if ( R <= m ) return queryl ( R , v , lson ) ;
pii tmp = queryl( R , v , rson ) ;
if ( tmp.ft < v ) return tmp ;
return queryl ( R , v , lson ) ;
}
pii queryr ( int L , int v , int rt , int l , int r ) {
if ( L <= l ) {
if ( val[rt] % v == 0 ) return pii ( v , l ) ;
else if ( l == r ) return pii ( gcd ( v , val[rt] ) , l ) ;
}
int m = l + r >> 1 ;
if ( m < L ) return queryr ( L , v , rson ) ;
pii tmp = queryr ( L , v , lson ) ;
if ( tmp.ft < v ) return tmp ;
return queryr ( L , v , rson ) ;
}
void getl ( int i )
{
int nowgcd = a[i] , lastgcd = query ( 1 , i , root ) , x = i ;
G[0].push_back ( pii ( a[i] , i ) ) ;
while ( nowgcd != lastgcd )
{
pii y = queryl ( x , nowgcd , root ) ;
G[0].push_back ( y ) ;
x = y.sd ;
nowgcd = y.ft ;
}
G[0].push_back ( pii ( nowgcd , 0 ) ) ;
}
void getr ( int i )
{
int nowgcd = a[i] , lastgcd = query ( i , n , root ) , x = i ;
G[1].push_back ( pii ( a[i] , i ) ) ;
while ( nowgcd != lastgcd ) {
pii y = queryr ( x , nowgcd , root ) ;
G[1].push_back ( y ) ;
x = y.sd ;
nowgcd = y.ft ;
}
G[1].push_back ( pii ( nowgcd , n + 1 ) ) ;
}
void add ( int x , int y )
{
if ( vis[x] == 0 ) ++ ans ;
vis[x] += y ;
if ( vis[x] == 0 ) -- ans ;
}
void calc ( int i , int f )
{
G[0].clear () ;
G[1].clear () ;
getl ( i ) ;
getr ( i ) ;
for ( int i=1;i