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