版权声明:本文为博主原创文章,转载请说明出处。 https://blog.csdn.net/xianpingping/article/details/83151895
嗯。反正这道题当时忘记了树状数组差分。用的线段树。比赛时写这么长的线段树时间上多少有点吃亏。
就是两个树,维护区间加1操作,然后分别查两棵树的最小值。
树状数组差分:
#include<bits/stdc++.h>
using namespace std;
const int maxn=100000+100;
const int mod=998244353;
const int inf=0x3f3f3f3f;
typedef long long LL;
LL sum1[maxn];
LL sum2[maxn];
int n;
LL lowbit(int x){
return x&(-x);
}
LL add(int x,LL *C,int k){
while(x<maxn){
C[x]+=k;
x+=lowbit(x);
}
}
LL sum(int x,LL *C){
LL ans=0;
while(x>0){
ans+=C[x];
x-=lowbit(x);
}
return ans;
}
LL powmod(LL a,LL n){
LL ans=1;
while(n){
if(n&1)
ans=(ans*a)%mod;
a=(a*a)%mod;
n>>=1;
}
return ans;
}
int main()
{
int t,n,m;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
memset(sum1,0,sizeof(sum1));
memset(sum2,0,sizeof(sum2));
for(int i=1;i<=m;i++){
int l,r,c;
scanf("%d%d%d",&l,&r,&c);
if(c==2){
add(l,sum1,1);
add(r+1,sum1,-1);
}
else{
add(l,sum2,1);
add(r+1,sum2,-1);
}
}
LL minn1=inf;
LL minn2=inf;
for(int i=1;i<=n;i++){
minn1=min(minn1,sum(i,sum1));
minn2=min(minn2,sum(i,sum2));
}
minn1=powmod(2,minn1);
minn2=powmod(3,minn2);
cout<<(minn1*minn2)%mod<<endl;
}
return 0;
}
/*
2
5 3
1 3 2
3 5 2
1 5 3
6 3
1 2 2
5 6 2
1 6 2
*/
比赛时写的线段树:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define lson l,mid,id*2
#define rson mid+1,r,id*2+1
typedef long long LL;
const int inf=0x3f3f3f3f;
const int modif=998244353;
const int maxn=100000+100;
LL sum2[maxn<<2];
///LL minn2[maxn<<2];
LL lazy2[maxn<<2];
LL sum3[maxn<<2];
///LL minn3[maxn<<2];
LL lazy3[maxn<<2];
void pushdown3(LL id,LL m){
if(lazy3[id]){
lazy3[id*2]+=lazy3[id];
lazy3[id*2+1]+=lazy3[id];
sum3[id*2]+=lazy3[id];
sum3[id*2+1]+=lazy3[id];
lazy3[id]=0;///标记root状态已更新
}
}
void pushup3(LL id){
sum3[id]=min(sum3[id*2],sum3[id*2+1]);
lazy3[id]=0;
}
void update3(LL l,LL r,LL id,LL L,LL R,LL w){
if(l>=L && r<=R)
{
lazy3[id]+=w;///标志当前这段区间更新了,但是这段区间下边的还没有更新
sum3[id]=sum3[id]+w;
return ;
}
pushdown3(id,r-l+1);///如果这次更新过程中有靠下的,就会一直更新,下放
LL mid=(l+r)/2;
if(L<=mid){
update3(lson,L,R,w);
}
if(R>mid){
update3(rson,L,R,w);
}
pushup3(id);
}
LL query3(LL l,LL r,LL id,LL L,LL R){
LL ans=inf;
if(l>=L &&r<=R){
return sum3[id];
}
pushdown3(id,r-l+1);///查的时候遇到靠下的也要一直下放
LL mid=(l+r)/2;
if(L<=mid){
ans=min(ans,query3(lson,L,R));
}
if(R>mid){
ans=min(ans,query3(rson,L,R));
}
pushup3(id);
return ans;
}
void pushdown2(LL id,LL m){
if(lazy2[id]){
lazy2[id*2]+=lazy2[id];
lazy2[id*2+1]+=lazy2[id];
sum2[id*2]+=lazy2[id];
sum2[id*2+1]+=lazy2[id];
lazy2[id]=0;///标记root状态已更新
}
}
void pushup2(LL id){
sum2[id]=min(sum2[id*2],sum2[id*2+1]);
lazy2[id]=0;
}
void update2(LL l,LL r,LL id,LL L,LL R,LL w){
if(l>=L && r<=R)
{
lazy2[id]+=w;///标志当前这段区间更新了,但是这段区间下边的还没有更新
sum2[id]=sum2[id]+w;
return ;
}
pushdown2(id,r-l+1);///如果这次更新过程中有靠下的,就会一直更新,下放
LL mid=(l+r)/2;
if(L<=mid){
update2(lson,L,R,w);
}
if(R>mid){
update2(rson,L,R,w);
}
pushup2(id);
}
LL query2(LL l,LL r,LL id,LL L,LL R){
LL ans=inf;
if(l>=L &&r<=R){
return sum2[id];
}
pushdown2(id,r-l+1);///查的时候遇到靠下的也要一直下放
LL mid=(l+r)/2;
/// LL ans=inf;
if(L<=mid){
ans=min(ans,query2(lson,L,R));
}
if(R>mid){
ans=min(ans,query2(rson,L,R));
}
pushup2(id);
return ans;
}
int main()
{
int t,n,m,aa,bb,cc;
scanf("%d",&t);
while(t--){
memset(sum2,0,sizeof(sum2));
memset(lazy3,0,sizeof(lazy3));
memset(sum3,0,sizeof(sum3));
memset(lazy2,0,sizeof(lazy2));
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d%d%d",&aa,&bb,&cc);
if(cc==2)
update2(1,n,1,aa,bb,1);
else
update3(1,n,1,aa,bb,1);
}
LL lala2=query2(1,n,1,1,n);
LL lala3=query3(1,n,1,1,n);
LL res=1;
//cout<<lala2<<" "<<lala3<<endl;
if(lala2>0)
{
for(int i=0;i<lala2;i++)
res=(res*2)%modif;
}
if(lala3>0)
{
for(int i=0;i<lala3;i++)
res=(res*3)%modif;
}
//cout<<res2<<" "<<res3<<endl;
cout<<res<<endl;
}
}