2018.09.19测试

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

猜你喜欢

转载自blog.csdn.net/qq_40942982/article/details/82781097
今日推荐