线段树
1.
题意:输入t,为有t组数据,每组数据先输入 n,m表示有n个点,m个操作,下面有m行,每行有三个数,前两个为一个区间,把这个区间中的 每个数都乘以最后一个数,最后一个数只能是 2,3;求,最后这个n个数的最大公倍数,刚开始这n个数都是1
线段树记录区间中出现2的次数和3的次数
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define MAX 100050
typedef long long ll;
struct Tree
{
int two,three;
int lazy_two;
int lazy_three;
int l,r;
}tree[4*MAX];
int n,m;
void push_up(int i)
{
tree[i].three=min(tree[i<<1].three,tree[i<<1|1].three);
tree[i].two=min(tree[i<<1].two,tree[i<<1|1].two);
}
void push_down(int i)
{
if(tree[i].lazy_two)
{
tree[i<<1].two+=tree[i].lazy_two;
tree[i<<1].lazy_two+=tree[i].lazy_two;
tree[i<<1|1].two+=tree[i].lazy_two;
tree[i<<1|1].lazy_two+=tree[i].lazy_two;
tree[i].lazy_two=0;
}
if(tree[i].lazy_three)
{
tree[i<<1].three+=tree[i].lazy_three;
tree[i<<1].lazy_three+=tree[i].lazy_three;
tree[i<<1|1].three+=tree[i].lazy_three;
tree[i<<1|1].lazy_three+=tree[i].lazy_three;
tree[i].lazy_three=0;
}
}
void build(int l,int r,int i)
{
tree[i].l=l;
tree[i].r=r;
if(l==r)
{
tree[i].three=0;
tree[i].two=0;
tree[i].lazy_three=0;
tree[i].lazy_two=0;
return ;
}
int mid=(l+r)>>1;
build(l,mid,i<<1);
build(mid+1,r,i<<1|1);
push_up(i);
}
void updata(int l,int r,int v,int i)
{
if(tree[i].l>=l&&tree[i].r<=r)
{
if(v==2)
{
tree[i].two++;
tree[i].lazy_two++;
return ;
}
if(v==3)
{
tree[i].three++;
tree[i].lazy_three++;
return ;
}
}
push_down(i);
int mid=(tree[i].l+tree[i].r)>>1;
if(mid>=l) updata(l,r,v,i<<1);
if(mid<r) updata(l,r,v,i<<1|1);
push_up(i);
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
memset(tree,0,sizeof(tree));
scanf("%d%d",&n,&m);
build(1,n,1);
for(int i=0;i<m;i++)
{
int l,r,v;
scanf("%d%d%d",&l,&r,&v);
updata(l,r,v,1);
}
ll ans=1;
for(int i=0;i<tree[1].two;i++)
ans=(ans*2)%998244353;
for(int i=0;i<tree[1].three;i++)
ans=(ans*3)%998244353;
//cout <<two<<endl;
//cout <<three<<endl;
cout <<ans<<endl;
}
return 0;
}