zoukankan      html  css  js  c++  java
  • Gym 101466K 树状数组+时间戳

    题目链接


    题意:
    有一颗根为0的树,每个顶点都有一个权值,有两种操作。

    • SEED u x 节点u的权值乘上x
    • RAND u 输出以节点u为根的子树的节点权值的乘积

    思路:
    每个权值很大,乘积会超出整数范围,考虑使用,质数指数表示法,分解质因数。
    乘积就是各个质因数指数的加和。
    使用dfs访问一边树,对于某个子树来说,dfs访问的时间戳是连续的,起点是子树的根。要求得乘积也就是去求某个连续的区间的和,可以使用树状数组来解决。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <vector>
    #include <algorithm>
    using namespace std;
    typedef long long LL;
    const int INF = 0x3f3f3f3f;
    const int N = 2e5 + 5;
    const int mod = 1e9 + 7;
    struct Value
    {
    	LL prime[8];
    	Value(){memset(prime, 0, sizeof(prime));}
    };
    vector<int> G[N];
    int fa[N];
    int prime[] = {2,3,5,7,11,13}, prime_cnt = 6;
    int start[N], over[N], dfs_clock;
    
    LL quick_exp(LL a, LL n){
    	LL ans = 1;
    	while(n){
    		if(n&1) ans = (ans*a)%mod;
    		n >>= 1;
    		a = (a*a)%mod;
    	}
    	return ans;
    }
    Value multip(Value a, Value b){
    	Value ans;
    	for(int i = 0; i < prime_cnt; i++)
    		ans.prime[i] = a.prime[i] + b.prime[i];
    	return ans;
    }
    
    Value get_value(LL x){
    	Value val;
    	for(int i = 0; i < prime_cnt; i++){
    		if(x % prime[i] == 0){
    			while(x % prime[i] == 0){
    				val.prime[i]++;
    				x /= prime[i];
    			}
    		}
    	}
    	return val;
    }
    
    LL get_LL(Value a){
    	LL ans = 1;
    	for(int i = 0; i < prime_cnt; i++)
    	{
    		ans = ans*quick_exp(prime[i], a.prime[i]);
    		ans %= mod;
    	}
    	return ans;
    }
    
    LL get_divitor_num(Value x){
    	LL ans = 1;
    	for(int i = 0; i < prime_cnt; i++)
    		ans = (ans*(x.prime[i]+1))%mod;
    	return ans;
    }
    
    Value val[N];
    Value p[N];
    int n, u, v;
    
    void init(){
    	memset(fa, -1, sizeof(fa));
    	for(int i = 0; i < N; i++){
    		G[i].clear();
    		start[i] = over[i] = 0;
    	}
    	dfs_clock = 0;
    }
    
    void dfs(int u){
    	start[u] = ++dfs_clock;
    	for(int i = 0; i < (int)G[u].size(); i++){
    		int v = G[u][i];
    		dfs(v);
    	}
    	over[u] = dfs_clock;
    }
    
    inline int lowbit(int i){
    	return i&(-i);
    }
    void add(int x, Value v){
    	for(int i = x; i < N; i += lowbit(i) ){
    		for(int j = 0; j < prime_cnt; j++){
    			p[i].prime[j] += v.prime[j];
    		}
    	}
    }
    Value sum(int x){
    	Value ans;
    	for(int i = x; i ; i -= lowbit(i)){
    		for(int j = 0; j < prime_cnt; j++){
    			ans.prime[j] += p[i].prime[j];
    		}
    	}
    	return ans;
    }
    Value query(int l, int r){
    	Value ans;
    	Value R = sum(r);
    	Value L = sum(l-1);
    	for(int i = 0; i < prime_cnt; i++){
    		ans.prime[i] = R.prime[i] - L.prime[i];
    	}
    	return ans;
    }
    
    int main()
    {
    	// freopen("in.txt", "r", stdin);
    	init();
    	scanf("%d", &n);
    	for(int i = 0; i < n-1; i++){
    		scanf("%d%d", &u, &v);
    		G[u].push_back(v);
    		fa[v] = u;
    	}
    	for(int i = 0; i < n; i++){
    		LL tmp;
    		scanf("%lld", &tmp);
    		val[i] = get_value(tmp);
    	}
    	dfs(0);
    	for(int i = 0; i < n; i++)
    	{
    		// cout << start[i] << " " << over[i] << endl;
    		add(start[i], val[i]);
    	}
    
    
    	int q,a;
    	LL x;
    	char cmd[10];
    	scanf("%d", &q);
    	while(q--){
    		scanf("%s", cmd);
    		if(cmd[0] == 'S'){
    			scanf("%d%lld", &a, &x);
    			Value extra = get_value(x);
    			add(start[a], extra);
    		}
    		else if(cmd[0] == 'R'){
    			scanf("%d", &a);
    			int L = start[a], R = over[a];
    			// cout << L << " " << R << endl;
    			Value ans = query(L, R);
    			printf("%lld %lld
    ", get_LL(ans), get_divitor_num(ans));
    		}
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    spring boot集成redis和mongodb实现计步排名
    spring boot + redis 实现网站限流和接口防刷功能
    基于spring-boot-data-jdbc的RowMapper实例的初始化配置,配置内容和实体类的代码由测试类生成
    自定义注解并封装成jar包,实现一般方法和Controller类的入参、出参和执行时间的日志打印
    封装自己的spring-boot-starter实现初始化字典数据和脱敏(windows10+jdk8+idea+spring-boot2.1.5)
    spring boot 集成mybatis的多数据源
    常用工具说明--jsdoc 前端文档输出工具
    常用工具说明--mysql数据库安装
    web前端--实现前后端分离的心得
    资料汇总--Ajax中Put和Delete请求传递参数无效的解决方法(Restful风格)【转】
  • 原文地址:https://www.cnblogs.com/Alruddy/p/7707725.html
Copyright © 2011-2022 走看看