蒟蒻刚学线段树,求调
查看原帖
蒟蒻刚学线段树,求调
924768
liaohaoyu7楼主2024/7/22 21:30

思路不太一样,样例没过,求大佬帮忙

#include <iostream>
#include <cmath>
#include <cstdio>
using namespace std;

const int N=1e5+12;
long long n,q,m,floor_;
long long a[N],tree[N<<2],tag[N<<2];

long long lchild(long long p){
	return p<<1;
}

long long rchild(long long p){
	return p<<1|1;
}

void push_up(long long p){
	tree[p]=tree[lchild(p)]+tree[rchild(p)];
}

void build(long long p,long long pl,long long pr){
	tag[p]=0;
	if (pl==pr){
		tree[p]=a[pl];
		return ;
	}
	long long mid=(pl+pr)>>1;
	build(lchild(p),pl,mid); //构建左子树 
	build(rchild(p),mid+1,pr); //构建右子树 
	push_up(p); //
}

//void gettag(long long L,long long R,long long k){
//	floor_=ceil(log2(n))
//	int num=pow(2,floor_-1)-1;//该层上面的数的个数 
//	int rest=n-num; //该层的剩余个数 
//	int p=num+L; 
//	while(p<=num+R){
//		if (p==rest+num) {
//			floor_--;
//			num=pow(2,floor_)-1;
//			
//		}
//		
//	}
//	for (int i=num+L;i<=num+R && i<=num+rest;i++){
//		tag[i]=tree[i]*(k-1);
//		cout<<i<<" ";
//		cout<<tag[i]<<endl;
//		tag[i]%=m;
//	}
//	for (int i=)
//	return ;
//}

void gettag(long long L,long long R,long long k,long long now,long long cnt){
//	if (lchild(now)) gettag(L,R,k,lchild(now),cnt);
	if (lchild(now)>n && rchild(now)>n) {
		return ;
	}
	if (lchild(now)) gettag(L,R,k,lchild(now),cnt);
	if (lchild(now)>n && rchild(now)>n) {
		++cnt;
		if (L<=cnt && cnt<=R) tag[now]+=(tree[now]*(k-1));
		cout<<now<<" "<<(tree[now]*(k))<<endl;
		return ;
	}
	if (rchild(now)) gettag(L,R,k,rchild(now),cnt);
	return ;
}

void addtag(long long p,long long pl,long long pr,long long d){ //d为未修改值 
	tag[p]+=d; //打上标记 
	tree[p]+= (pr-pl+1)*d; //更新tree 
}

//更新子节点(若有tag标记,则更新) 
void push_down(long long p,long long pl,long long pr){
	if (tag[p]) {
		long long mid=(pl+pr)>>1;
		addtag(lchild(p),pl,mid,tag[p]);//将tag标记传给左子树 
		addtag(rchild(p),mid+1,pr,tag[p]);//将tag标记传给右子树
		tag[p]=0;//tag标记被传走,归零 
	}
}

//L:左端点 R:右端点 p:线段位置 pl、pr:线段区间 d:修改值 
void updata(long long L,long long R,long long p,long long pl,long long pr,long long d){
	if (L<=pl && pr<=R){
		addtag(p,pl,pr,d);
		return ;
	} 
	push_down(p,pl,pr); //如果不能覆盖,就将tag传递给子树 
	long long mid=(pl+pr)>>1;
	if (L<=mid) updata(L,R,lchild(p),pl,mid,d);
	if (R>mid) updata(L,R,rchild(p),mid+1,pr,d);
	push_up(p);//修改之后传参 
}

long long query(long long L,long long R,long long p,long long pl,long long pr){
	if (L<=pl && pr<=R) return tree[p];
	push_down(p,pl,pr);//先查看是否有tag标记并更新有标记的tag的节点的子节点
	long long ret=0;
	long long mid=(pl+pr)>>1;
	if (L<=mid) ret+=query(L,R,lchild(p),pl,mid),ret%=m;
	if (R>mid) ret+=query(L,R,rchild(p),mid+1,pr),ret%=m;
	return ret%m; 
}

int main(){

	scanf("%lld %lld %lld",&n,&q,&m);
	floor_=ceil(log2(n));
	for (int i=1;i<=n;i++){
		scanf("%lld",&a[i]);
	}
	build(1,1,n);
	while(q--){
		long long op,L,R,k;
		scanf("%lld",&op);
		if (op==1) {
			scanf("%lld %lld %lld",&L,&R,&k);
//			updata(L,R,1,1,n,k);
//			cout<<1;
			gettag(L,R,k,1,0);
			updata(L,R,1,1,n,k);
		} 
		else if (op==2){
			scanf("%lld %lld %lld",&L,&R,&k);
			updata(L,R,1,1,n,k);
		}
		else {
			scanf("%lld %lld",&L,&R);
			printf("%lld\n",query(L,R,1,1,n));
		}
	}
	return 0;
}

2024/7/22 21:30
加载中...