1. 程式人生 > 其它 >Python經典程式設計習題100例:第4例

Python經典程式設計習題100例:第4例

在基礎線段樹的模板上做了優化,具體看eval函式和push_down.

#include <bits/stdc++.h>
#define ll long long
#define fi first
#define se second
#define pb push_back
#define me memset
#define rep(a,b,c) for(int a=b;a<=c;++a)
#define per(a,b,c) for(int a=b;a>=c;--a)
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
using namespace std;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b) {return a/gcd(a,b)*b;}

int n,m,p;
int a[N];
int l,r,d;

struct Node{
	int l,r;
	int sum,add,mul;
}tr[N<<2];

void push_up(int u){
	tr[u].sum=(tr[u<<1].sum+tr[u<<1|1].sum)%p;
}

void eval(Node &root,ll add,ll mul){
	root.sum=((ll)root.sum*mul+(ll)(root.r-root.l+1)*add)%p;
	root.mul=((ll)root.mul*mul)%p;
	root.add=((ll)root.add*mul+add)%p;
}

void push_down(int u){
	eval(tr[u<<1],tr[u].add,tr[u].mul);
	eval(tr[u<<1|1],tr[u].add,tr[u].mul);
	tr[u].add=0;
	tr[u].mul=1;
}

void build(int u,int l,int r){
	if(l==r) tr[u]={l,r,a[r],0,1};
	else{
		tr[u]={l,r,0,0,1};
		int mid=(l+r)>>1;
		build(u<<1,l,mid);
		build(u<<1|1,mid+1,r);
		push_up(u);
	}
}

void modify(int u,int l,int r,ll add,ll mul){
	if(tr[u].l>=l && tr[u].r<=r) eval(tr[u],add,mul);
	else{
		push_down(u);
		int mid=(tr[u].l+tr[u].r)>>1;
		if(l<=mid) modify(u<<1,l,r,add,mul);
		if(r>mid) modify(u<<1|1,l,r,add,mul);
		push_up(u);
	}
}

ll query(int u,int l,int r){
	if(tr[u].l>=l && tr[u].r<=r) return tr[u].sum;
	
	push_down(u);

	int mid=(tr[u].l+tr[u].r)>>1;
	
	ll sum=0;

	if(l<=mid) sum=query(u<<1,l,r);
	if(r>mid) sum=(sum+query(u<<1|1,l,r))%p;
	return sum;
}

int main() {
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

	cin>>n>>m>>p;

	rep(i,1,n) cin>>a[i];

	build(1,1,n);

	while(m--){
		int op;
		cin>>op;
		if(op==1){
			cin>>l>>r>>d;
			modify(1,l,r,0,d);
		}
		else if(op==2){
			cin>>l>>r>>d;
			modify(1,l,r,d,1);
		}
		else{
			cin>>l>>r;
			cout<<query(1,l,r)<<'\n';
		}
	}


    return 0;
}