P3373 【模板】线段树 2 有点问题,求改!!
  • 板块题目总版
  • 楼主_int128
  • 当前回复0
  • 已保存回复0
  • 发布时间2024/7/7 13:18
  • 上次更新2024/7/7 15:51:15
查看原帖
P3373 【模板】线段树 2 有点问题,求改!!
681392
_int128楼主2024/7/7 13:18
#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll n,m,q;
const int MAXN=100005;
ll a[MAXN]={};
struct node{
	int l,r;
	ll dat,tag,tag1;//tag为懒标记 
}ST[4*MAXN];//线段树最坏情况下为4*n 
void build(int node_num,int l,int r){//node_num为ST中的下标 
	ST[node_num].l=l;
	ST[node_num].r=r;
	ST[node_num].tag=0;
	ST[node_num].tag1=1;
	if(l==r){
		ST[node_num].dat=a[l];
		return ;
	}
	int mid=(l+r)/2;
	build(node_num*2,l,mid);
	build(node_num*2+1,mid+1,r);
	ST[node_num].dat=ST[node_num*2].dat+ST[node_num*2+1].dat;
}//建立了一个线段树
void push_down(int node_num){//下传标记的函数 
	if(ST[node_num].tag==0&&ST[node_num].tag1==0){
		return ;
	}
	int mid=(ST[node_num].l+ST[node_num].r)/2;
	ST[node_num*2].dat*=ST[node_num].tag1;
	ST[node_num*2].dat+=ST[node_num].tag*(mid-ST[node_num].l+1);
	ST[node_num*2].tag1*=ST[node_num].tag1;
	ST[node_num*2].tag+=ST[node_num].tag;
	
	ST[node_num*2+1].dat*=ST[node_num].tag1;
	ST[node_num*2+1].dat+=ST[node_num].tag*(ST[node_num].r-mid);
	ST[node_num*2+1].tag1*=ST[node_num].tag1;
	ST[node_num*2+1].tag+=ST[node_num].tag;
	
	ST[node_num].tag=0;//标记已完全下传,标记清零
	ST[node_num].tag1=1; 
}
ll ask(int node_num,int tar_l,int tar_r){//询问node_num结点tar_l~tar-r的区间和 
	int mid=(ST[node_num].l+ST[node_num].r)/2;
	if(ST[node_num].l>=tar_l&&ST[node_num].r<=tar_r){
		return ST[node_num].dat;
	}
	push_down(node_num);
	ll res=0;
	if(mid>=tar_l){
		res+=ask(node_num*2,tar_l,tar_r);
		res=res%q;
	}
	if(mid<tar_r){
		res+=ask(node_num*2+1,tar_l,tar_r);
		res=res%q;
	}
	return res;
}
void add(int node_num,int tar_l,int tar_r,ll val){//将node_num结点下所有tar_l~tar_r的结点加val(懒标记的更新)
	int mid=(ST[node_num].l+ST[node_num].r)/2;
	if(ST[node_num].l>=tar_l&&ST[node_num].r<=tar_r){
		ST[node_num].dat+=val*(ST[node_num].r-ST[node_num].l+1);//增加该结点的区间和
		ST[node_num].tag+=val; 
		return ;
	}
	push_down(node_num);
	if(mid>=tar_l){
		add(node_num*2,tar_l,tar_r,val);
	}
	if(mid<tar_r){
		add(node_num*2+1,tar_l,tar_r,val);
	}
	ST[node_num].dat=ST[node_num*2].dat+ST[node_num*2+1].dat;
}
void add1(int node_num,int tar_l,int tar_r,ll val){//将node_num结点下所有tar_l~tar_r的结点乘val(懒标记的更新)
	int mid=(ST[node_num].l+ST[node_num].r)/2;
	if(ST[node_num].l>=tar_l&&ST[node_num].r<=tar_r){
		ST[node_num].dat*=val;
		ST[node_num].tag*=val;
		ST[node_num].tag1*=val;
		return ;
	}
	push_down(node_num);
	if(mid>=tar_l){
		add1(node_num*2,tar_l,tar_r,val);
	}
	if(mid<tar_r){
		add1(node_num*2+1,tar_l,tar_r,val);
	}
	ST[node_num].dat=ST[node_num*2].dat+ST[node_num*2+1].dat;
}
int main(){
	//freopen("D://P3373_2.in","r",stdin);
	cin>>n>>m>>q;
	ll res[MAXN]={},t=1;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	build(1,1,n);
	for(int i=1;i<=m;i++){
		int type;
		cin>>type;
		if(type==1){//乘法 
			ll xx,yy,k;
			cin>>xx>>yy>>k;
			add1(1,xx,yy,k);
		}else if(type==2){//加法 
			ll xx,yy,k;
			cin>>xx>>yy>>k;
			add(1,xx,yy,k);
		}else{//输出 
			ll xx,yy;
			cin>>xx>>yy;
			res[t]=ask(1,xx,yy);
			t++;
		}
	}
	for(int i=1;i<t;i++){
		cout<<res[i]%q<<endl;
	} 
	return 0;
}
2024/7/7 13:18
加载中...