zoukankan      html  css  js  c++  java
  • [洛谷P4074][WC2013]糖果公园

    题目大意:给一棵$n$个节点的树,每个点有一个值$C_i$,每次询问一条路径$x->y$,求$sumlimits_{c}val_c imes sumlimits_{i=1}^{cnt_c}worth_i(cnt_c=sumlimits_{iin(x->y)}[C_i==c])$。带修改

    题解:树上带修莫队,在普通的树上莫队上加一维时间即可

    卡点:$res$忘记开$long;long$

    C++ Code:

    #include <cstdio>
    #include <algorithm>
    #define maxn 100010
    #define N (maxn << 1)
    #define bl(x) ((x) >> 11)
    int n, m, l, r, p;
    long long res;
    long long ans[maxn];
    int C[maxn], num[maxn];
    long long W[maxn], V[maxn];
    bool vis[maxn];
    int Qcnt, Mcnt;
    struct Query {
    	int l, r, tim, id, lca;
    	bool addlca;
    	inline bool operator < (const Query &rhs) const {
    		return (bl(l) == bl(rhs.l)) ? (bl(r) == bl(rhs.r) ? tim < rhs.tim : r < rhs.r) : l < rhs.l;
    	}
    } q[maxn];
    inline void swap(int &a, int &b) {a ^= b ^= a ^= b;}
    struct Modity {
    	int pos, C, tim;
    	inline void modify() {
    		if (vis[pos]) {
    			res -= W[num[::C[pos]]--] * V[::C[pos]];
    			res += W[++num[C]] * V[C];
    		}
    		swap(::C[pos], C);
    	}
    } M[maxn];
    
    int date[N], in[maxn], out[maxn], idx;
    namespace tree {
    	int head[maxn], cnt;
    	struct Edge {
    		int to, nxt;
    	} e[maxn << 1];
    	void add(int a, int b) {
    		e[++cnt] = (Edge) {b, head[a]}; head[a] = cnt;
    		e[++cnt] = (Edge) {a, head[b]}; head[b] = cnt;
    	}
    	
    	int fa[maxn];
    	void dfs(int u) {
    		date[in[u] = ++idx] = u;
    		for (int i = head[u]; i; i = e[i].nxt) {
    			int v = e[i].to;
    			if (v != fa[u]) {
    				fa[v] = u;
    				dfs(v);
    			}
    		}
    		date[out[u] = ++idx] = u;
    	}
    }
    
    namespace tarjan {
    	int head[maxn], cnt;
    	struct QUERY {
    		int v, nxt, id;
    	} Q[maxn << 1];
    	void add(int a, int b, int c) {
    		Q[++cnt] = (QUERY) {b, head[a], c}; head[a] = cnt;
    		Q[++cnt] = (QUERY) {a, head[b], c}; head[b] = cnt;
    	}
    	
    	int f[maxn];
    	void init(int n) {
    		for (int i = 1; i <= n; i++) f[i] = i;
    	}
    	int find(int x) {return (x == f[x] ? x : (f[x] = find(f[x])));}
    	void dfs(int u) {
    		for (int i = tree::head[u]; i; i = tree::e[i].nxt) {
    			int v = tree::e[i].to;
    			if (v != tree::fa[u]) {
    				dfs(v);
    				f[v] = find(u);
    			}
    		}
    		for (int i = head[u]; i; i = Q[i].nxt) q[Q[i].id].lca = find(Q[i].v);
    	}
    }
    
    #define ONLINE_JUDGE
    #include <cctype>
    namespace R {
        int x;
        #ifdef ONLINE_JUDGE
        char *ch, op[1 << 26];
        inline void init() {
            fread(ch = op, 1, 1 << 26, stdin);
        }
        inline int read() {
            while (isspace(*ch)) ch++;
            for (x = *ch & 15, ch++; isdigit(*ch); ch++) x = x * 10 + (*ch & 15);
            return x;
        }
        #else
        char ch;
        inline int read() {
            ch = getchar();
            while (isspace(ch)) ch = getchar();
            for (x = ch & 15, ch = getchar(); isdigit(ch); ch = getchar()) x = x * 10 + (ch & 15);
            return x;
        }
        #endif
    }
    
    int O;
    int main() {
        #ifdef ONLINE_JUDGE
        R::init();
        #endif
        tarjan::init(n = R::read()); m = R::read(), O = R::read();
        for (int i = 1; i <= m; i++) V[i] = R::read();
        for (int i = 1; i <= n; i++) W[i] = R::read();
        for (int i = 1; i < n; i++) tree::add(R::read(), R::read());
        tree::dfs(1);
        for (int i = 1; i <= n; i++) C[i] = R::read();
        for (int i = 1; i <= O; i++) {
        	if (R::read()) {
    			q[++Qcnt].tim = i;
        		tarjan::add(q[Qcnt].l = R::read(), q[Qcnt].r = R::read(), q[Qcnt].id = Qcnt);
    		} else M[++Mcnt].pos = R::read(), M[Mcnt].C = R::read(), M[Mcnt].tim = i;
    	}
    	tarjan::dfs(1);
    	for (int i = 1; i <= Qcnt; i++) {
    		int &l = q[i].l, &r = q[i].r;
    		if (in[l] > in[r]) swap(l, r);
    		l = (q[i].addlca = (q[i].lca != l)) ? out[l] : in[l];
    		r = in[r];
    	}
    	std::sort(q + 1, q + Qcnt + 1);
    	l = 1, r = 0, p = 0;
    	for (int i = 1; i <= Qcnt; i++) {
    		while (l > q[i].l) (vis[date[--l]] ^= 1) ? (res += W[++num[C[date[l]]]] * V[C[date[l]]]) : (res -= W[num[C[date[l]]]--] * V[C[date[l]]]);
    		while (r < q[i].r) (vis[date[++r]] ^= 1) ? (res += W[++num[C[date[r]]]] * V[C[date[r]]]) : (res -= W[num[C[date[r]]]--] * V[C[date[r]]]);
    		while (l < q[i].l) (vis[date[l]] ^= 1) ? (res += W[++num[C[date[l]]]] * V[C[date[l++]]]) : (res -= W[num[C[date[l]]]--] * V[C[date[l++]]]);
    		while (r > q[i].r) (vis[date[r]] ^= 1) ? (res += W[++num[C[date[r]]]] * V[C[date[r--]]]) : (res -= W[num[C[date[r]]]--] * V[C[date[r--]]]);
    		while (p < Mcnt && M[p + 1].tim < q[i].tim) M[++p].modify();
    		while (p && M[p].tim > q[i].tim) M[p--].modify();
    		ans[q[i].id] = res + (q[i].addlca ? W[num[C[q[i].lca]] + 1] * V[C[q[i].lca]] : 0);
    	}
    	for (int i = 1; i <= Qcnt; i++) printf("%lld
    ", ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    KVM快速构建虚拟机
    工程师测试
    配置SMB,NFS
    Shell脚本基础应用
    Web网页部署
    基础邮件,mariadb数据库
    SElinux,firewalld配置
    Linux管理员测试
    磁盘分区
    配置权限,LDAP
  • 原文地址:https://www.cnblogs.com/Memory-of-winter/p/9635426.html
Copyright © 2011-2022 走看看