HDU-6273 Master of GCD(思維,線段樹)
阿新 • • 發佈:2019-02-13
題意:
輸入T組資料,每組資料有n個數,m個操作,下面有m行,每行有三個數,前兩個為區間,把這個區間中每個數都乘以第三個數(只會是 2,3)求最後這n個數的最大公約數,剛開始這n個數都是1 。
題解:
記錄每個數乘上的2和3的數量,結果就是最少數量的2和最少數量的3的乘積。
程式碼:
#include <cstdio> #include <algorithm> #include <cstring> #include <cmath> using namespace std; const int MAXN = 100005; const int MOD = 998244353; struct T{ int num2,num3; int lazy2,lazy3; }Tree[MAXN*3]; void Up(int temp){ Tree[temp].num2 = min(Tree[temp<<1].num2,Tree[temp<<1|1].num2); Tree[temp].num3 = min(Tree[temp<<1].num3,Tree[temp<<1|1].num3); } void Build(int temp,int l,int r){ Tree[temp].num2 = Tree[temp].num3 = 0; Tree[temp].lazy2 = Tree[temp].lazy3 = 0; if(l == r)return; int m = l + (r-l)/2; Build(temp<<1,l,m); Build(temp<<1|1,m+1,r); } void PushDown(int temp){ if(Tree[temp].lazy2){ Tree[temp<<1].lazy2 += Tree[temp].lazy2; Tree[temp<<1].num2 += Tree[temp].lazy2; Tree[temp<<1|1].lazy2 += Tree[temp].lazy2; Tree[temp<<1|1].num2 += Tree[temp].lazy2; Tree[temp].lazy2 = 0; } if(Tree[temp].lazy3){ Tree[temp<<1].lazy3 += Tree[temp].lazy3; Tree[temp<<1].num3 += Tree[temp].lazy3; Tree[temp<<1|1].lazy3 += Tree[temp].lazy3; Tree[temp<<1|1].num3 += Tree[temp].lazy3; Tree[temp].lazy3 = 0; } } void Updata(int temp,int l,int r,int ql,int qr,int value){ if(ql>r || qr<l)return; if(ql<=l && qr>=r){ if(value == 2){ Tree[temp].num2++; Tree[temp].lazy2++; } else{ Tree[temp].num3++; Tree[temp].lazy3++; } return ; } PushDown(temp); int m = l + (r-l)/2; if(ql <= m)Updata(temp<<1,l,m,ql,qr,value); if(qr > m)Updata(temp<<1|1,m+1,r,ql,qr,value); Up(temp); } int main(){ int T,n,m; scanf("%d",&T); while(T--){ scanf("%d %d",&n,&m); Build(1,1,n); int a,b,value; while(m--){ scanf("%d %d %d",&a,&b,&value); Updata(1,1,n,a,b,value); } long long sum = 1; for(int i=1 ; i<=Tree[1].num2 ; ++i)sum = (sum*2)%MOD; for(int i=1 ; i<=Tree[1].num3 ; ++i)sum = (sum*3)%MOD; printf("%lld\n",sum); } return 0; }