为何我的线段树,慢得如此销魂
查看原帖
为何我的线段树,慢得如此销魂
222901
隔壁泞2的如心楼主2023/2/19 21:34

rt,不求调,只求分析复杂度是否是 O(n2)O(n^2)……

#include<cstdio>
#include<algorithm>
#include<cassert>
#define ull unsigned long long
using namespace std;
struct poitrans{
	ull mat[5][5];
	friend poitrans operator*(poitrans p1,poitrans p2){
		poitrans p3={{{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0}}};
		for(int i=0;i<5;i++){
			for(int j=0;j<5;j++){
				for(int h=0;h<5;h++){
					p3.mat[i][j]+=p1.mat[i][h]*p2.mat[h][j];
				}
			}
		}
		return p3;
	}
}tra[1049000];
struct poimsg{
	ull len,sa,sb,sab,sans;
	friend poimsg operator*(poimsg p1,poitrans p2){
		return
		{
		p1.len*p2.mat[0][0]+p1.sa*p2.mat[1][0]+p1.sb*p2.mat[2][0]+p1.sab*p2.mat[3][0]+p1.sans*p2.mat[4][0],
		p1.len*p2.mat[0][1]+p1.sa*p2.mat[1][1]+p1.sb*p2.mat[2][1]+p1.sab*p2.mat[3][1]+p1.sans*p2.mat[4][1],
		p1.len*p2.mat[0][2]+p1.sa*p2.mat[1][2]+p1.sb*p2.mat[2][2]+p1.sab*p2.mat[3][2]+p1.sans*p2.mat[4][2],
		p1.len*p2.mat[0][3]+p1.sa*p2.mat[1][3]+p1.sb*p2.mat[2][3]+p1.sab*p2.mat[3][3]+p1.sans*p2.mat[4][3],
		p1.len*p2.mat[0][4]+p1.sa*p2.mat[1][4]+p1.sb*p2.mat[2][4]+p1.sab*p2.mat[3][4]+p1.sans*p2.mat[4][4],
		};
	}
	friend poimsg operator+(poimsg p1,poimsg p2){
		return {p1.len+p2.len,p1.sa+p2.sa,p1.sb+p2.sb,p1.sab+p2.sab,p1.sans+p2.sans};
	}
}seg[1049000]; 
struct qur{
	int l,r,id;
	friend bool operator<(qur q1,qur q2){
		return q1.r<q2.r;
	}
}lx[305416],sta1[305416],sta2[305416];
int t,un=1,n,q,a[256789],b[256789],tp1,tp2;
ull ans[305416];
void psdn(int now){
	if(now<<1>=un*2)return;
	seg[now<<1]=seg[now<<1]*tra[now];
	seg[now<<1|1]=seg[now<<1|1]*tra[now];
	tra[now<<1]=tra[now<<1]*tra[now];
	tra[now<<1|1]=tra[now<<1|1]*tra[now];
	tra[now]={{{1,0,0,0,0},{0,1,0,0,0},{0,0,1,0,0},{0,0,0,1,0},{0,0,0,0,1}}}; 
}
void mf(int lb,int rb,ull x,int mode,int now=1,int l=0,int r=un-1){
	if(l>rb||r<lb)return;
	if(l>=lb&&r<=rb){
		switch(mode){
			case 1:{
				seg[now]=seg[now]*(poitrans){{{1,x,0,0,0},{0,0,0,0,0},{0,0,1,x,0},{0,0,0,0,0},{0,0,0,0,1}}};
				tra[now]=tra[now]*(poitrans){{{1,x,0,0,0},{0,0,0,0,0},{0,0,1,x,0},{0,0,0,0,0},{0,0,0,0,1}}};
				break;
			}
			case 2:{
				seg[now]=seg[now]*(poitrans){{{1,0,x,0,0},{0,1,0,x,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,1}}};
				tra[now]=tra[now]*(poitrans){{{1,0,x,0,0},{0,1,0,x,0},{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,1}}};
				break;
			}
			case 3:{
				seg[now]=seg[now]*(poitrans){{{1,0,0,0,0},{0,1,0,0,0},{0,0,1,0,0},{0,0,0,1,1},{0,0,0,0,1}}};
				tra[now]=tra[now]*(poitrans){{{1,0,0,0,0},{0,1,0,0,0},{0,0,1,0,0},{0,0,0,1,1},{0,0,0,0,1}}};
				break;
			}
		}
		return;
	}
	int mid=(l+r)>>1;
	psdn(now);
	mf(lb,rb,x,mode,now<<1,l,mid);mf(lb,rb,x,mode,now<<1|1,mid+1,r);
	seg[now]=seg[now<<1]+seg[now<<1|1];
}
ull ck(int lb,int rb,int now=1,int l=0,int r=un-1){
	if(l>rb||r<lb)return 0;
	if(l>=lb&&r<=rb){
		return seg[now].sans;
	}
	psdn(now);
	int mid=(l+r)>>1;
	return ck(lb,rb,now<<1,l,mid)+ck(lb,rb,now<<1|1,mid+1,r);
}
void arg(int now=1,int l=0,int r=un-1){
	seg[now].len=r+1-l;
	tra[now]={{{1,0,0,0,0},{0,1,0,0,0},{0,0,1,0,0},{0,0,0,1,0},{0,0,0,0,1}}}; 
	if(l==r)return;
	int mid=(l+r)>>1;
	arg(now<<1,l,mid);arg(now<<1|1,mid+1,r);
}
int main(){
	scanf("%d%d",&t,&n);
	while(un<=n)un<<=1;
	arg();
	for(int i=1;i<=n;i++)scanf("%d",a+i);
	for(int i=1;i<=n;i++)scanf("%d",b+i);
	scanf("%d",&q);
	for(int i=1;i<=q;i++){
		int in1,in2;
		scanf("%d%d",&in1,&in2);
		lx[i]={in1,in2,i};
	}
//	for(int h=1;h<un*2;h++){
//			printf("%d %llu %llu %llu %llu %llu\n",h,seg[h].len,seg[h].sa,seg[h].sb,seg[h].sab,seg[h].sans);
//		}
	sort(lx+1,lx+q+1);
	for(int i=1,j=1;i<=n;i++){
		int l1=i,l2=i;
		while(tp1&&sta1[tp1].id<a[i])l1=sta1[tp1--].l;
		while(tp2&&sta2[tp2].id<b[i])l2=sta2[tp2--].l;
		mf(l1,i,a[i],1);mf(l2,i,b[i],2);mf(1,i,1,3);
//		printf("____i=%d %d %d\n",i,l1,l2);
		while(lx[j].r<=i&&j<=q){
			assert(lx[j].r==i);
			ans[lx[j].id]=ck(lx[j].l,lx[j].r);
			j++;
		}
///		for(int h=1;h<un*2;h++){
//			printf("%d %llu %llu %llu %llu %llu\n",h,seg[h].len,seg[h].sa,seg[h].sb,seg[h].sab,seg[h].sans);
//		}
		sta1[++tp1]={l1,i,a[i]};sta2[++tp2]={l2,i,b[i]};
	}
	for(int i=1;i<=q;i++)printf("%llu\n",ans[i]);
}
/*
5 5
1 2 3 4 5
5 4 3 2 1
10
1 2 2 3 3 4 4 5
1 3 2 4 3 5
1 4 2 5
1 5
*/
2023/2/19 21:34
加载中...