wust1593线段树

来源:互联网 发布:pes2017曼城数据 编辑:程序博客网 时间:2024/05/22 00:44

题目大意:给你n个数,m次操作,操作有两种 0 l r ,计算n个数从l乘到r后置0的个数,1 a b ,将a位置换位b。每个数均小于100,n,m< 100000.

思路:简单的线段树,每个节点维护该区间拥有的2的因子个数,5的因子个数,以及数据里是否拥有0.

每次计算,如果有0输出1,否则输出因子2和5的最小个数。

ps:记录0的个数的时候没有0忘记初始化为0.。。。。。。。


#include <iostream>#include <cstdio>#include <string>#include <cstring>#include <fstream>#include <algorithm>#include <cmath>#include <queue>#include <stack>#include <vector>#include <map>#include <set>#include <iomanip>using namespace std;#pragma comment(linker, "/STACK:102400000,102400000")#define maxn 200005#define MOD 1000000007#define mem(a , b) memset(a , b , sizeof(a))#define LL long long#define ULL long longconst long long INF=0x3fffffff;int arr[maxn];int n , m;int num_tree;struct tree{    int left , right ;    int num2 , num5 , num0;}ST[3*maxn];int get2(int n){    int ans = 0;    while(n % 2 == 0 && n)    {        n /= 2;        ans ++;    }    return ans;}int get5(int n){    int ans = 0;    while(n % 5 == 0 && n)    {        n /= 5;        ans ++;    }    return ans;}void Build(int root , int left , int right){    ST[root].left = left;    ST[root].right = right;    if(left == right)    {        ST[root].num2 = get2(arr[left]);        ST[root].num5 = get5(arr[left]);        if(arr[left] == 0) ST[root].num0 = 1;        else ST[root].num0 = 0;        return ;    }    int mid = (left + right) / 2;    Build(2 * root , left , mid);    Build(2 * root + 1 , mid + 1 , right);    ST[root].num0 = ST[root*2].num0 + ST[2*root + 1].num0;    ST[root].num2 = ST[root*2].num2 + ST[2*root + 1].num2;    ST[root].num5 = ST[root*2].num5 + ST[2*root + 1].num5;}void update(int root ,int pos , int val){    if(pos < ST[root].left || pos > ST[root].right) return ;    int mid = (ST[root].right + ST[root].left) / 2;    if(pos == ST[root].left && pos == ST[root].right)    {        ST[root].num2 = get2( val );        ST[root].num5 = get5( val );        if(val == 0) ST[root].num0 = 1;        else ST[root].num0 = 0;        return ;    }    if(pos <= mid) update(2*root , pos , val);    else update(2 * root + 1 , pos ,val);    ST[root].num0 = ST[root*2].num0 + ST[2*root + 1].num0;    ST[root].num2 = ST[root*2].num2 + ST[2*root + 1].num2;    ST[root].num5 = ST[root*2].num5 + ST[2*root + 1].num5;}int Query(int l , int r , int pos , int flag){    if(ST[pos].left > r || ST[pos].right < l)    {          return 0 ;    }    int temp = (ST[pos].right + ST[pos].left) / 2;    if(ST[pos].left == l && ST[pos].right == r)    {        if(flag == 0) return ST[pos].num0;        else if(flag == 2) return ST[pos].num2;        else return ST[pos].num5;    }    else if(r <= temp)        return Query(l , r , 2 * pos , flag);    else if(l > temp)        return Query(l , r , 2 * pos + 1 , flag);    else if(l <= temp && r > temp)        return Query(l , temp , 2 * pos , flag) + Query(temp + 1, r , 2 * pos + 1 , flag);}int main(){    while(scanf("%d %d" , &n , &m) != EOF)    {        for(int i = 1 ; i <= n ; i++)        {            scanf("%d" , &arr[i]);        }        if(n == 0 ) continue;        Build(1 , 1 , n);        int a , b , c;        for(int i = 0 ; i < m ; i ++ )        {            scanf("%d %d %d" , &a , &b , &c);            if(a)            {                update(1 , b , c);            }            else            {                if(b > c) swap(b , c);                if(Query(b , c , 1 , 0))                    printf("1\n");                else                    printf("%d\n" , min(Query(b , c , 1 , 2 ) , Query(b , c , 1 , 5) ) );            }        }    }    return 0;}


0 0