您的位置:首页 > 大数据 > 人工智能

玲珑杯#3 G 1043 - G. Quailty and Square Counter【线段树-卡常数】

2016-09-30 18:19 387 查看
题目链接:1043 - G. Quailty and Square Counter

首先,x向x^2%2017建边,跑一跑找找规律,能发现环套树一共有14个,每个的环最大6,且在环上的点一共64个,且不在环上的点到环的常数最多5。知道这样的性质后,就简单了,区间平方直接暴力,区间赋值直接搞,暴力的话到某个区间为相同数时停止。

其实上面都不是重点,大家都会,卡常才是最重要的,我从本地43s卡到11.6s,交上去跑了7s。

my code:

#include <bits/stdc++.h>
using namespace std ;

typedef long long LL ;

#define clr( a , x ) memset ( a , x , sizeof a )
#define root 1 , 1 , n
#define ls o << 1
#define rs o << 1 | 1
#define lson ls , l , m
#define rson rs , m + 1 , r

const int MAXN = 100005 ;
const int mod = 2017 ;

int be[mod][2] , step[mod][10] , len[mod] , vis[mod] , S[mod] , top , cas ;
unsigned long long T[MAXN * 3] , all[15] , res ;
int same[MAXN * 3] , shift[MAXN * 3] , in[MAXN * 3] , setv[MAXN * 3] ;
bitset < 2017 > G[MAXN * 3] , ans ;
int n , m ;

void preprocess () {
cas = 0 ;
for ( int i = 0 ; i < mod ; ++ i ) {
step[i][0] = i ;
for ( int j = 1 ; j < 10 ; ++ j ) {
step[i][j] = step[i][j - 1] * step[i][j - 1] % mod ;
}
}
int now = 0 ;
for ( int i = 0 ; i < mod ; ++ i ) if ( !vis[i] ) {
int x = i , ok = 1 ;
vis[x] = -1 ;
top = 0 ;
S[top ++] = x ;
while ( 1 ) {
x = x * x % mod ;
if ( !vis[x] ) {
vis[x] = -1 ;
S[top ++] = x ;
}
else if ( vis[x] == 1 ) {
ok = 0 ;
break ;
} else {
ok = 1 ;
break ;
}
}
if ( ok == 1 ) {
for ( int j = 0 ; j < top ; ++ j ) {
if ( S[j] == x ) {
len[++ cas] = top - j ;
all[cas] = 0 ;
for ( int k = j ; k < top ; ++ k ) {
all[cas] |= 1ULL << now ;
be[S[k]][0] = cas ;
be[S[k]][1] = now ++ ;
}
break ;
}
}
}
for ( int j = 0 ; j < top ; ++ j ) {
vis[S[j]] = 1 ;
}
}
}

void up ( int o ) {
int tmp = in[o] ;
T[o] = T[ls] | T[rs] ;
in[o] = in[ls] & in[rs] ;
//G[o] = G[ls] | G[rs] ;
if ( same[ls] == same[rs] ) same[o] = same[ls] ;
else same[o] = -1 ;
if ( tmp && in[o] ) return ;
if ( in[o] ) G[o].reset () ;
else if ( in[ls] ) G[o] = G[rs] ;
else if ( in[rs] ) G[o] = G[ls] ;
else {
G[o] = G[ls] ;
if ( same[o] == -1 ) G[o] |= G[rs] ;
}
}

void Shift ( int o , int s ) {
int &x = same[o] ;
shift[o] += s ;
if ( !~x ) {
unsigned long long t = 0 ;
for ( int i = 1 ; i <= 14 ; ++ i ) {
unsigned long long tmp = all[i] & T[o] ;
if ( !tmp ) continue ;
int a = s % len[i] ;
int b = len[i] - a ;
t |= ( ( tmp << a ) | ( tmp >> b ) ) & all[i] ;
}
T[o] = t ;
} else {
//s step
if ( s <= 5 ) {
if ( be[x][0] ) T[o] = 0 ;
else G[o][x] = 0 ;
x = step[x][s] ;
if ( be[x][0] ) T[o] = 1ULL << be[x][1] , in[o] = 1 ;
else G[o][x] = 1 , in[o] = 0 ;
} else {
if ( be[x][0] ) T[o] = 0 ;
else G[o][x] = 0 ;
x = step[x][6] ;
s -= 6 ;
s %= len[be[x][0]] ;
x = step[x][s] ;
if ( be[x][0] ) T[o] = 1ULL << be[x][1] , in[o] = 1 ;
else G[o][x] = 1 , in[o] = 0 ;
}
}
}

void Same ( int o , int x ) {
T[o] = 0 ;
shift[o] = 0 ;
if ( !in[o] ) {
if ( ~same[o] ) {
if ( x != same[o] ) G[o][same[o]] = 0 ;
} else G[o].reset () ;
}
setv[o] = same[o] = x ;
if ( be[x][0] ) T[o] = 1ULL << be[x][1] , in[o] = 1 ;
else G[o][x] = 1 , in[o] = 0 ;
}

void down ( int o ) {
if ( ~setv[o] ) {
Same ( ls , setv[o] ) ;
Same ( rs , setv[o] ) ;
setv[o] = -1 ;
}
if ( shift[o] ) {
Shift ( ls , shift[o] ) ;
Shift ( rs , shift[o] ) ;
shift[o] = 0 ;
}
}

void update ( int L , int R , int x , int o , int l , int r ) {
if ( L <= l && r <= R ) {
if ( ~x ) Same ( o , x ) ;
else {
if ( l == r ) Shift ( o , 1 ) ;
else {
if ( in[o] || ~same[o] ) Shift ( o , 1 ) ;
else {
down ( o ) ;
int m = l + r >> 1 ;
update ( L , R , x , lson ) ;
update ( L , R , x , rson ) ;
up ( o ) ;
}
}
}
return ;
}
down ( o ) ;
int m = l + r >> 1 ;
if ( L <= m ) update ( L , R , x , lson ) ;
if ( m <  R ) update ( L , R , x , rson ) ;
up ( o ) ;
}

void query ( int L , int R , int o , int l , int r ) {
if ( L <= l && r <= R ) {
res |= T[o] ;
if ( !in[o] ) ans |= G[o] ;
return ;
}
down ( o ) ;
int m = l + r >> 1 ;
if ( L <= m ) query ( L , R , lson ) ;
if ( m <  R ) query ( L , R , rson ) ;
}

void build ( int o , int l , int r ) {
setv[o] = -1 ;
shift[o] = 0 ;
if ( l == r ) {
int x ;
scanf ( "%d" , &x ) ;
G[o].reset () ;
T[o] = 0 ;
if ( be[x][0] ) T[o] = 1ULL << be[x][1] , in[o] = 1 ;
else G[o][x] = 1 , in[o] = 0 ;
same[o] = x ;
return ;
}
int m = l + r >> 1 ;
build ( lson ) ;
build ( rson ) ;
up ( o ) ;
}

void show ( int o , int l , int r ) {
if ( l == r ) {
//printf ( "%d%c" , same[o] , l == n ? '\n' : ' ' ) ;
return ;
}
int m = l + r >> 1 ;
down ( o ) ;
show ( lson ) ;
show ( rson ) ;
}

void solve ( int T ) {
scanf ( "%d%d" , &n , &m ) ;
build ( root ) ;
for ( int i = 0 ; i < m ; ++ i ) {
int op , l , r , x ;
scanf ( "%d%d%d" , &op , &l , &r ) ;
if ( op == 1 ) update ( l , r , -1 , root ) ;
else if ( op == 2 ) {
scanf ( "%d" , &x ) ;
update ( l , r , x , root ) ;
} else {
res = 0 ;
ans.reset () ;
//show ( root ) ;
query ( l , r , root ) ;
int num = ans.count () + __builtin_popcountll ( res ) ;
printf ( "%d\n" , num ) ;
}
}
}

int main () {
preprocess () ;
int T ;
//freopen ( "H.in" , "r" , stdin ) ;
//freopen ( "h1.txt" , "w" , stdout ) ;
scanf ( "%d" , &T ) ;
for ( int i = 1 ; i <= T ; ++ i ) {
solve ( i ) ;
}
//printf ( "%.5f\n" , ( double ) clock () / CLOCKS_PER_SEC ) ;
return 0 ;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: