T1
我的做法貌似和标程不一样,但我感觉这样是可以做得,然后有几个大测试点没过,应该是ll或者取模哪个地方炸了8,反正做法应该是对的
两次离散化+线段树,复杂度为O(mlogm)
下面是半红半绿的code qwq
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <ctime>
#define LL long long
#define maxm 400100
using namespace std;
const LL mo=998244353;
LL n,ans;
int m,end;
int ll[maxm<<2],rr[maxm<<2];
LL num[maxm],e[maxm],maxi[maxm<<2],mmax[maxm<<2],tag[maxm<<2];
struct qwq
{
LL l,r,a;
}q[maxm];
LL read()
{
LL xx=0,kk=1;char ch=' ';
while(!isdigit(ch)){ch=getchar();if(ch=='-')kk=-1;}
while(isdigit(ch)){xx=xx*10+ch-'0';ch=getchar();}
return kk*xx;
}
LL poww(LL x)
{
x=x%mo;
return x*1ll*x%mo;
}
void build(int l,int r,int num)
{
ll[num]=l,rr[num]=r;
if(l==r) return;
int mid=(l+r)>>1;
build(l,mid,num<<1);
build(mid+1,r,num<<1|1);
}
void pushdown(int num)
{
if(!tag[num]) return;
tag[num<<1]=max(tag[num<<1],tag[num]);
tag[num<<1|1]=max(tag[num<<1|1],tag[num]);
maxi[num<<1]=max(maxi[num<<1],tag[num<<1]);
maxi[num<<1|1]=max(maxi[num<<1|1],tag[num<<1|1]);
tag[num]=0;
}
void modify(int l,int r,LL a,int num)
{
if(ll[num]>r||rr[num]<l)return;
if(ll[num]>=l&&rr[num]<=r)
{
maxi[num]=max(maxi[num],a);
tag[num]=max(tag[num],a);
return;
}
pushdown(num);
modify(l,r,a,num<<1);
modify(l,r,a,num<<1|1);
maxi[num]=max(maxi[num<<1],maxi[num<<1|1]);
}
void update(int l,int r,int num)
{
if(ll[num]>r||rr[num]<l) return;
if(ll[num]==rr[num]){mmax[ll[num]]=maxi[num];return;}
pushdown(num);
update(l,r,num<<1);
update(l,r,num<<1|1);
}
int main()
{
freopen("segment.in","r",stdin);
freopen("segment.out","w",stdout);
n=read(),m=read();
for(int i=1;i<=m;++i)
{
q[i].l=read(),q[i].r=read(),q[i].a=read();
num[(i-1)<<1]=e[(i-1)<<1]=q[i].l;
num[(i-1)<<1|1]=e[(i-1)<<1|1]=q[i].r;
}
sort(e,e+2*m);
end=unique(e,e+2*m)-e;
for(int i=1;i<end;++i)
e[end+i-1]=(e[i-1]+e[i])>>1;
sort(e,e+2*end-2);
end=unique(e,e+2*end-2)-e;
for(int i=0;i<=2*(m-1)+1;++i)
num[i]=lower_bound(e,e+end,num[i])-e+1;
build(1,end,1);
for(int i=1;i<=m;++i)
modify(num[(i-1)<<1],num[(i-1)<<1|1],q[i].a,1);
update(1,end,1);
for(int i=1;i<=end;++i)
ans=(ans+poww(mmax[i]))%mo;
for(int i=2;i<=end;++i)
{
LL len=(e[i-1]-e[i-2]-1)%mo;
if(mmax[i-1]<=mmax[i]) ans=(ans+(1ll*len*poww(mmax[i-1]))%mo)%mo;
else ans=(ans+(1ll*len*poww(mmax[i])%mo))%mo;
}
printf("%lld",ans);
return 0;
}
/*
3 3
1 2 1
2 3 3
1 3 2
*/
T2
又是一道辣鸡数据结构题呢。口区
T3
打表好题!!
我们可以通过打表找到f的规律,然后推一下g的式子我们可以得到
g(n)=$$\sum_{i=1}^{n} f(i)$$
g(g(n))=$$\sum_{i=1}^{n} i*f(i)$$
然后是玄学code...
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <ctime>
#define LL long long
#define maxn 400100
using namespace std;
const LL mo=998244353;
LL n,ans1,ans2,f[maxn];
int main()
{
scanf("%lld",&n);
LL l=1,r;
f[1]=1;f[2]=2;
ans1=1,ans2=1;
for(int i=2;l<n;++i)
{
r=min(n,l+f[i]);
for(int j=l+1;j<min((LL)5e5,r);++j) f[j]=i;
ans1=(ans1+1ll*(r-l)*i%mo)%mo;
ans2=(ans2+1ll*(((r+l+1)*(r-l)>>1)%mo)*i)%mo;
l=r;
}
printf("%lld %lld",ans1,ans2);
return 0;
}