zoukankan      html  css  js  c++  java
  • 【LOJ】#2116. 「HNOI2015」开店

    题解

    一道我觉得和二叉树没有关系的题……

    因为直接上点分就过了,虽然很慢,而且代码很长

    你需要记录一个点分树,对于每个点分树的重心,记录一下上一次进行分割时树的重心以及这个重心和上一次重心所连接的点以及连接的边的距离
    然后计算这个重心和所在的树到上一个重心节点路径和的前缀和,还有节点个数和

    处理每棵树的节点路径前缀和和节点个数前缀和

    处理的时候枚举这个点经过的每个重心,统计过重心的路径和即可

    代码

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define mp make_pair
    #define pb push_back
    #define enter putchar('
    ')
    #define space putchar(' ')
    #define MAXN 150005
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    typedef long double db;
    typedef unsigned int u32;
    template<class T>
    void read(T &res) {
        res = 0;char c = getchar();T f = 1;
        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) {putchar('-');x = -x;}
        if(x >= 10) out(x / 10);
        putchar('0' + x % 10);
    }
    int N,Q,A,num[MAXN],fa[MAXN],siz[MAXN],son[MAXN],dis[MAXN];
    vector<int> age[MAXN],aux[MAXN],dis_fa[MAXN],siztr[MAXN],siztr_fa[MAXN];
    vector<int64> sum[MAXN],sum_fa[MAXN];
    int que[MAXN],ql,qr,id[MAXN],dfn[MAXN],idx,pre[MAXN],pos[MAXN],pre_dis[MAXN];
        
    bool vis[MAXN];
    struct node {
        int to,next;
        int64 val;
    }E[MAXN * 2];
    
    int head[MAXN],sumE;
    void add(int u,int v,int64 c) {
        E[++sumE].next = head[u];
        E[sumE].to = v;
        E[sumE].val = c;
        head[u] = sumE;
    }
    int CalcG(int st) {
        que[ql = qr = 1] = st;
        fa[st] = 0;
        while(ql <= qr) {
    	int u = que[ql++];siz[u] = 1;son[u] = 0;
    	for(int i = head[u] ; i ; i = E[i].next) {
    	    int v = E[i].to;
    	    if(v != fa[u] && !vis[v]) {
    		que[++qr] = v;fa[v] = u;
    	    }
    	}
        }
        int res = que[qr];
        for(int i = qr ; i >= 1 ; --i) {
    	int u = que[i];
    	if(fa[u]) {
    	    siz[fa[u]] += siz[u];
    	    son[fa[u]] = max(son[fa[u]],siz[u]);
    	}
    	son[u] = max(son[u],qr - siz[u]);
    	if(son[u] < son[res]) res = u;
        }
        return res;
    }
    void Calc(int st,int64 val) {
        que[ql = qr = 1] = st;fa[st] = 0;dis[st] = val;
        while(ql <= qr) {
    	int u = que[ql++];
    	for(int i = head[u] ; i ; i = E[i].next) {
    	    int v = E[i].to;
    	    if(!vis[v] && v != fa[u]) {
    		dis[v] = dis[u] + E[i].val;
    		fa[v] = u;
    		que[++qr] = v;
    	    }
    	}
        }
    }
    int64 S(int u,int R) {
        int siz =  aux[u].size();
        int64 res = 0;
        for(int i = 0 ; i < siz - 1; ++i) {
    	int z = aux[u][i],y = aux[u][i + 1];
    	int t = upper_bound(age[z].begin(),age[z].end(),R) - age[z].begin() - 1;
    	res += 1LL * (siztr[z][t] - siztr_fa[y][t]) * dis_fa[u][i] + sum[z][t] - sum_fa[y][t];
        }
        res += sum[u][upper_bound(age[u].begin(),age[u].end(),R) - age[u].begin() - 1];
        return res;
    }
    bool cmp(int a,int b) {
        return num[a] < num[b];
    }
    void dfs_G(int u,int f,int64 c) {
        int G = CalcG(u);
        dfn[++idx] = G;
        pre[G] = f;pos[G] = u;pre_dis[G] = c;vis[G] = 1;
        for(int i = head[G] ; i; i =  E[i].next) {
    	int v = E[i].to;
    	if(!vis[v]) dfs_G(v,G,E[i].val);
        }
    }
    void Init() {
        read(N);read(Q);read(A);
        for(int i = 1 ; i <= N ; ++i) read(num[i]);
        
        for(int i = 1 ; i < N ; ++i) {
    	int u,v;int64 c;
    	read(u);read(v);read(c);
    	add(u,v,c);add(v,u,c);
        }
        dfs_G(1,0,0);
        memset(vis,0,sizeof(vis));
        for(int i = 1 ; i <= idx ; ++i) {
    	int G = dfn[i];
    	if(pre[G]) {
    	    Calc(pos[G],pre_dis[G]);
    	    sum_fa[G].resize(sum[pre[G]].size());
    	    siztr_fa[G].resize(sum[pre[G]].size());
    	    for(int i = 1 ; i <= qr ; ++i) {
    		int u = que[i];
    		int t = lower_bound(age[pre[G]].begin(),age[pre[G]].end(),num[u]) - age[pre[G]].begin();
    		sum_fa[G][t] += dis[u];
    		siztr_fa[G][t]++;
    	    }
    	    int s = sum_fa[G].size();
    	    for(int i = 1 ; i < s ; ++i) {sum_fa[G][i] += sum_fa[G][i - 1];siztr_fa[G][i] += siztr_fa[G][i - 1];}
    	}
    	Calc(G,0);
    	vis[G] = 1;
    	for(int i = 1 ; i <= qr ; ++i) id[i] = que[i];
    	sort(id + 1,id + qr + 1,cmp);
    	int s = 0;
    	sum[G].pb(0);age[G].pb(-1);siztr[G].pb(0);
    	for(int i = 1 ; i <= qr ; ++i) {
    	    int u = id[i];
    	    aux[u].pb(G);
    	    dis_fa[u].pb(dis[u]);
    	    if(i == 1 || num[u] != num[id[i - 1]]) {
    		age[G].pb(num[u]);
    		sum[G].pb(0);siztr[G].pb(0);++s;
    	    }
    	    sum[G][s] += dis[u];
    	    siztr[G][s]++;
    	}
    	for(int i = 1 ; i <= s ; ++i) {sum[G][i] += sum[G][i - 1];siztr[G][i] += siztr[G][i - 1];}
    	age[G].pb(A + 1);sum[G].pb(sum[G][s]);
        }
    }
    void Solve() {
        int64 ans = 0;
        int u,a,b;
        for(int i = 1 ; i <= Q ; ++i) {
    	read(u);read(a);read(b);
    	a = (a + ans) % A;b = (b + ans) % A;
    	if(a > b) swap(a,b);
    	ans = S(u,b) - S(u,a - 1);
    	out(ans);enter;
        }
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Init();
        Solve();
        return 0;
    }
    

    (谁来拯救一下我越写越慢越写越长的数据结构题= =)

  • 相关阅读:
    杨玲 201771010133《面向对象程序设计(java)》第三周学习总结
    杨玲 201771010133《面向对象程序设计(java)》第二周学习总结
    杨玲 201771010133 《面向对象程序设计(java)》第一周学习总结
    bzoj1010 [HNOI2008]玩具装箱toy
    hdu5115 Dire Wolf
    bzoj2880
    bzoj2301 [HAOI2011]Problem b
    bzoj2440 [中山市选2011]完全平方数
    bzoj4448 情报传递
    bzoj4445 小凸想跑步
  • 原文地址:https://www.cnblogs.com/ivorysi/p/9642625.html
Copyright © 2011-2022 走看看