1. 程式人生 > >HDU-6273 Master of GCD(思維,線段樹)

HDU-6273 Master of GCD(思維,線段樹)

題意:

輸入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;
}