zoukankan      html  css  js  c++  java
  • 【bzoj3211】花神游历各国 并查集+树状数组

    原文地址:http://www.cnblogs.com/GXZlegend/p/6809714.html


    题目描述

     

    输入

     

    输出

    每次x=1时,每行一个整数,表示这次旅行的开心度

    样例输入

    4
    1 100 5 5
    5
    1 1 2
    2 1 2
    1 1 2
    2 2 3
    1 1 4

    样例输出

    101
    11
    11


    题解

    并查集+树状数组,附带一点数学知识

    因为√1=1,且一个数x开接近log2(log2x)次平方后就会变成1,这个数是非常小的。

    所以我们完全可以暴力修改,只需要知道每次的修改区间中有多少真正需要修改的数即可。

    这可以用并查集来维护,b[i]表示i之后(包括i)第一个点权不为1的数的位置,当然还需要一个find函数。

    这样暴力修改,但是不能暴力求和,还需要用一个树状数组来维护区间和。

    注意开long long,并且把b[n+1]赋为n+1以防止越界。

    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    #define N 100010
    using namespace std;
    typedef long long ll;
    int n , b[N];
    ll w[N] , f[N];
    int find(int x)
    {
    	return b[x] == x ? x : b[x] = find(b[x]);
    }
    void update(int x , ll a)
    {
    	int i;
    	for(i = x ; i <= n ; i += i & -i) f[i] += a;
    }
    ll query(int x)
    {
    	int i;
    	ll ans = 0;
    	for(i = x ; i ; i -= i & -i) ans += f[i];
    	return ans;
    }
    int main()
    {
    	int m , i , opt , l , r;
    	ll tmp;
    	scanf("%d" , &n);
    	for(i = 1 ; i <= n ; i ++ )
    		scanf("%lld" , &w[i]) , b[i] = (w[i] <= 1 ? i + 1 : i) , update(i , w[i]);
    	b[n + 1] = n + 1;
    	scanf("%d" , &m);
    	while(m -- )
    	{
    		scanf("%d%d%d" , &opt , &l , &r);
    		if(opt == 1) printf("%lld
    " , query(r) - query(l - 1));
    		else
    		{
    			for(i = find(l) ; i <= r ; i = find(i + 1))
    			{
    				tmp = (ll)sqrt(w[i]) , update(i , tmp - w[i]) , w[i] = tmp;
    				if(w[i] <= 1) b[i] = find(i + 1);
    			}
    		}
    	}
    	return 0;
    }

     

  • 相关阅读:
    JS 寻路算法
    Fireworks基本使用
    html基础知识汇总(二)之Emmet语法
    JS函数式编程
    Web前端导航
    CSS样式一
    选择器的分类
    框架集
    表单标签元素
    图像热点&图像映射
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/6809714.html
Copyright © 2011-2022 走看看