[GXOI|GZOI2019]旧词
作者:互联网
题解
首先当\(k=1\)的时候肥肠简单
就是按照\(x\)从小到大排序
每处理到一个\(x\),就把\(1\to x\)的路径上的点都+1
然后查询\(y\)的时候就查询\(1\to y\)的点权和
那么\(k>1\)的时候也一样
对于深度为\(i\)的节点,给ta加上\(i^k-(i-1)^k\)即可
最后查询的时候查询点u的贡献就是$val[u] \times ( dep[u]^k-(dep[u]-1)^k ) $
可以用线段树维护
先记录每个节点的\((dep[u]^k-(dep[u]-1)^k)\)值
然后每次就是给一些节点的这个东西前面加一个系数
所以线段树维护一个区间\((dep[u]^k-(dep[u]-1)^k)\)之和来方便维护区间\(val[u] \times (dep[u]^k-(dep[u]-1)^k)\)之和
代码
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
const int M = 50005 ;
const int mod = 998244353 ;
using namespace std ;
inline int read() {
char c = getchar() ; int x = 0 , w = 1 ;
while(c>'9'||c<'0') { if(c=='-') w = -1 ; c = getchar() ; }
while(c>='0'&&c<='9') { x = x*10+c-'0' ; c = getchar() ; }
return x*w ;
}
int n , m , k , cnt ;
int tp[M] , fa[M] , p[M] , size[M] ;
int ans[M] , dep[M] , w[M] , son[M] ;
int id[M] , val[M] , top[M] ;
struct Q { int x , y , idx ; } q[M] ;
vector < int > vec[M] ;
inline bool operator < (Q a , Q b) { return a.x < b.x ; }
struct Node { int Bsm , sum , Tag ; } t[M * 4] ;
inline int Fpw(int Base , int k) {
int temp = 1 ;
while(k) {
if(k & 1) temp = 1LL * temp * Base % mod ;
Base = 1LL * Base * Base % mod ; k >>= 1 ;
}
return temp ;
}
void dfs1(int u , int father) {
dep[u] = dep[father] + 1 ; size[u] = 1 ; int mx = -1 ;
for(int i = 0 , v ; i < vec[u].size() ; i ++) {
v = vec[u][i] ; dfs1(v , u) ;
size[u] += size[v] ; if(size[v] > mx) mx = size[v] , son[u] = v ;
}
}
void dfs2(int u , int topf) {
top[u] = topf ; id[u] = ++ cnt ; val[cnt] = w[u] ;
if(!son[u]) return ; dfs2(son[u] , topf) ;
for(int i = 0 , v ; i < vec[u].size() ; i ++) {
v = vec[u][i] ;
if(!id[v]) dfs2(v , v) ;
}
}
# define ls (now << 1)
# define rs (now << 1 | 1)
inline void pushup(int now) {
t[now].Bsm = (t[ls].Bsm + t[rs].Bsm) % mod ;
t[now].sum = (t[ls].sum + t[rs].sum) % mod ;
}
void build(int l , int r , int now) {
if(l == r) { t[now].Bsm = val[l] ; return ; }
int mid = (l + r) >> 1;
build(l , mid , ls) ; build(mid + 1 , r , rs) ;
pushup(now) ;
}
inline void update(int now , int k) {
t[now].sum = (t[now].sum + 1LL * k * t[now].Bsm % mod) % mod ;
t[now].Tag = (t[now].Tag + k) % mod ;
}
inline void pushdown(int now) {
if(t[now].Tag) {
update(ls , t[now].Tag) ;
update(rs , t[now].Tag) ;
t[now].Tag = 0 ;
}
}
void Change(int L , int R , int l , int r , int now) {
if(l > R || r < L) return ;
if(l >= L && r <= R) { update(now , 1) ; return ; }
int mid = (l + r) >> 1 ;
pushdown(now) ;
if(mid >= R) Change(L , R , l , mid , ls) ;
else if(mid < L) Change(L , R , mid + 1 , r , rs) ;
else Change(L , mid , l , mid , ls) , Change(mid + 1 , R , mid + 1 , r , rs) ;
pushup(now) ;
}
int qry(int L , int R , int l , int r , int now) {
if(l > R || r < L) return 0 ;
if(l >= L && r <= R) return t[now].sum ;
int mid = (l + r) >> 1 ;
pushdown(now) ;
if(mid >= R) return qry(L , R , l , mid , ls) ;
else if(mid < L) return qry(L , R , mid + 1 , r , rs) ;
else return ( qry(L , mid , l , mid , ls) + qry(mid + 1 , R , mid + 1 , r , rs) ) % mod ;
}
inline void Change(int x , int y) {
while(top[x] != top[y]) {
if(dep[top[x]] < dep[top[y]]) swap(x , y) ;
Change(id[top[x]] , id[x] , 1 , n , 1) ;
x = fa[top[x]] ;
}
if(dep[x] > dep[y]) swap(x , y) ;
Change(id[x] , id[y] , 1 , n , 1) ;
}
inline int query(int x , int y) {
int ret = 0 ;
while(top[x] != top[y]) {
if(dep[top[x]] < dep[top[y]]) swap(x , y) ;
ret = (ret + qry(id[top[x]] , id[x] , 1 , n , 1)) % mod ;
x = fa[top[x]] ;
}
if(dep[x] > dep[y]) swap(x , y) ;
ret = (ret + qry(id[x] , id[y] , 1 , n , 1)) % mod ;
return ret ;
}
# undef ls
# undef rs
int main() {
n = read() ; m = read() ; k = read() % (mod - 1) ;
for(int i = 1 ; i <= n ; i ++) {
tp[i] = Fpw(i , k) ;
p[i] = (tp[i] - tp[i - 1]) % mod ;
p[i] = (p[i] + mod) % mod ;
}
for(int i = 2 ; i <= n ; i ++) {
fa[i] = read() ;
vec[fa[i]].push_back(i) ;
}
dfs1(1 , 0) ;
for(int i = 1 ; i <= n ; i ++)
w[i] = p[dep[i]] ;
dfs2(1 , 1) ;
build(1 , n , 1) ;
for(int i = 1 ; i <= m ; i ++)
q[i].x = read() , q[i].y = read() , q[i].idx = i ;
sort(q + 1 , q + m + 1) ;
for(int i = 1 ; i <= m ; i ++) {
for(int j = q[i - 1].x + 1 ; j <= q[i].x ; j ++)
Change(1 , j) ;
ans[q[i].idx] = query(1 , q[i].y) ;
}
for(int i = 1 ; i <= m ; i ++) printf("%d\n",ans[i]) ;
return 0 ;
}
标签:int,top,mid,dep,GZOI2019,GXOI,旧词,now,mod 来源: https://www.cnblogs.com/beretty/p/10747162.html