题目大意:给你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 long
const 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;
}