zoukankan      html  css  js  c++  java
  • 【LOJ】#3088. 「GXOI / GZOI2019」旧词

    LOJ#3088. 「GXOI / GZOI2019」旧词

    不懂啊5e4感觉有点小

    就是离线询问,在每个x上挂上y的询问

    然后树剖,每个节点维护轻儿子中已经被加入的点的个数个数乘上(dep[u]^{k})

    新加一个点进去只会经过(log n)条轻边只会更新(log n)个节点

    然后再维护一下每个子树里被加入点的个数,每次查询一段重链的链尾要加上重儿子个数减去从y来的那个轻儿子的子树个数乘上(dep[u]^k)

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define mp make_pair
    #define pb push_back
    #define space putchar(' ')
    #define enter putchar('
    ')
    #define eps 1e-10
    #define MAXN 50005
    #define ba 47
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    typedef unsigned int u32;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;T f = 1;char c = getchar();
        while(c < '0' || c > '9') {
    	if(c == '-') f = -1;
    	c = getchar();
        }
        while(c >= '0' && c <= '9') {
    	res = res * 10 +c - '0';
    	c = getchar();
        }
        res *= f;
    }
    template<class T>
    void out(T x) {
        if(x < 0) {x = -x;putchar('-');}
        if(x >= 10) {
    	out(x / 10);
        }
        putchar('0' + x % 10);
    }
    const int MOD = 998244353;
    int inc(int a,int b) {
        return a + b >= MOD ? a + b - MOD : a + b;
    }
    int mul(int a,int b) {
        return 1LL * a * b % MOD;
    }
    void update(int &x,int y) {
        x = inc(x,y);
    }
    int fpow(int x,int c) {
        int res = 1,t = x;
        while(c) {
    	if(c & 1) res = mul(res,t);
    	t = mul(t,t);
    	c >>= 1;
        }
        return res;
    }
    struct node {
        int to,next;
    }E[MAXN * 2];
    int N,Q,K;
    int fa[MAXN],head[MAXN],sumE,x[MAXN],y[MAXN];
    int son[MAXN],top[MAXN],dfn[MAXN],siz[MAXN],idx,dep[MAXN],line[MAXN],ans[MAXN];
    vector<int> qry[MAXN];
    void add(int u,int v) {
        E[++sumE].to = v;
        E[sumE].next = head[u];
        head[u] = sumE;
    }
    void dfs1(int u) {
        siz[u] = 1;dep[u] = dep[fa[u]] + 1;
        for(int i = head[u] ; i; i = E[i].next) {
    	int v = E[i].to;
    	dfs1(v);
    	siz[u] += siz[v];
    	if(siz[v] > siz[son[u]]) son[u] = v;
        }
    }
    void dfs2(int u) {
        if(!top[u]) top[u] = u;
        dfn[u] = ++idx;
        line[idx] = u;
        if(!son[u]) return;
        top[son[u]] = top[u];
        dfs2(son[u]);
        for(int i = head[u] ; i ; i = E[i].next) {
    	int v = E[i].to;
    	if(v != son[u]) dfs2(v);
        }
    }
    struct tr_node {
        int l,r,sum,cnt;
    }tr[MAXN * 4];
    void update(int u) {
        tr[u].cnt = inc(tr[u << 1].cnt,tr[u << 1 | 1].cnt);
        tr[u].sum = inc(tr[u << 1].sum,tr[u << 1 | 1].sum);
    }
    void Add(int u,int pos,int ty) {
        if(tr[u].l == tr[u].r) {
    	if(ty == 0) update(tr[u].cnt,1);
    	else update(tr[u].sum,fpow(dep[line[pos]],K));
    	return;
        }
        int mid = (tr[u].l + tr[u].r) >> 1;
        if(pos <= mid) Add(u << 1,pos,ty);
        else Add(u << 1 | 1,pos,ty);
        update(u);
    }
    int Query(int u,int l,int r,int ty) {
        if(tr[u].l == l &&tr[u].r == r) {
    	if(ty == 0) return tr[u].cnt;
    	else return tr[u].sum;
        }
        int mid = (tr[u].l + tr[u].r) >> 1;
        if(r <= mid) return Query(u << 1,l,r,ty);
        else if(l > mid) return Query(u << 1 | 1,l,r,ty);
        else return inc(Query(u << 1,l,mid,ty),Query(u << 1 | 1,mid + 1,r,ty));
    }
    void build(int u,int l,int r) {
        tr[u].l = l;tr[u].r = r;
        if(l == r) {
    	tr[u].sum = 0;
    	return;
        }
        int mid = (l + r) >> 1;
        build(u << 1,l,mid);
        build(u << 1 | 1,mid + 1,r);
    }
    void Add_pos(int u) {
        Add(1,dfn[u],0);
        while(u) {
    	Add(1,dfn[u],1);
    	u = fa[top[u]];
        }
    }
    int Process(int y) {
        int pre = 0,res = 0;
        while(y) {
    	int d = fpow(dep[y],K);
    	update(res,Query(1,dfn[top[y]],dfn[y],1));
    	if(pre) update(res,MOD - mul(d,Query(1,dfn[pre],dfn[pre] + siz[pre] - 1,0)));
    	if(son[y]) update(res,mul(d,Query(1,dfn[son[y]],dfn[son[y]] + siz[son[y]] - 1,0)));
    	pre = top[y];y = fa[pre];
        }
        return res;
    }
    void Solve() {
        read(N);read(Q);read(K);
        for(int i = 2 ; i <= N ; ++i) {
    	read(fa[i]);
    	add(fa[i],i);
        }
        for(int i = 1 ; i <= Q ; ++i) {
    	read(x[i]);read(y[i]);
    	qry[x[i]].pb(i);
        }
        dfs1(1);dfs2(1);
        build(1,1,N);
        for(int i = 1 ; i <= N ; ++i) {
    	Add_pos(i);
    	for(auto id : qry[i]) {
    	    ans[id] = Process(y[id]);
    	}
        }
        for(int i = 1 ; i <= Q ; ++i) {
    	out(ans[i]);enter;
        }
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
    }
    
  • 相关阅读:
    Centos7网络配置(VMware)
    Djangoform表单Ajax控制跳转
    selenium Webdriver 处理iFrame之间的切换问题------------
    Eclipse相关的快捷键
    selenium webdriver----如何处理div弹窗、alert、confirm、prompt对话框-------------------
    处理basic认证,浏览器自带弹窗的(非windows弹窗)处理-----------------
    元素的Actions(特效)及基本UI控件操作
    查找页面元素一
    调用exe文件(一般处理登陆安全窗口)+睡眠等待(--------------------)
    用autoit识别windows窗口(保存弹窗及登陆(basic认证)相关的弹窗)-----
  • 原文地址:https://www.cnblogs.com/ivorysi/p/10978059.html
Copyright © 2011-2022 走看看