救命大佬qaq 30分(只过了1,3,4)救救孩子
查看原帖
救命大佬qaq 30分(只过了1,3,4)救救孩子
1103795
2301liuxiangyu楼主2025/2/5 09:32
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#define N 100010
#define lc p<<1
#define rc p<<1|1
long long int mod;

long long int w[N];


////////////////////////////////////////////////////气昏了,一会再来看











struct node
{
	long long int l;
	long long int r;
	long long int sum;
	long long int add;
	long long int mu;//初值为1
}tr[4 * N];



void build(long long int p, long long int l, long long int r) {//p为树的第几个节点
	tr[p] = { l,r,w[l],0,1 };
	if (l == r)
	{
		return;
	}
	else
	{
		long long int m = (l + r) / 2;
		build(lc, l, m);
		build(rc, m + 1, r);
		tr[p].sum = (tr[lc].sum % mod + tr[rc].sum % mod) % mod;
	}
}





//向下更新
void pushdown(long long int p) {
	//开始头疼了,好难

	//Q1:为啥要在这更新呢

	//A1: 我认为线段树“一条线”只能有一个懒标记节点,多了就乱了,会导致数据更新不及时出错
	//          所以下传懒标记时,若本层有懒标记则下传过去(?)  
	//Q2 :现在看来又不是这样呢 确实存在多个账本的情况
//   模拟一下)等会再想,等先写完的


	if (tr[p].add != 0)
	{
		tr[lc].add += tr[p].add % mod;
		tr[lc].add %= mod;
		tr[lc].sum += (tr[lc].r - tr[lc].l + 1) * tr[p].add % mod;
		tr[lc].sum %= mod;
		tr[rc].add += tr[p].add % mod;
		tr[rc].add %= mod;
		tr[rc].sum += (tr[rc].r - tr[rc].l +1 ) * tr[p].add % mod;
		tr[rc].sum %= mod;
		tr[p].add = 0;


	}

	//下传懒标记
}


void pushdown_mu(long long int p) {//此处为1!!!
	if (tr[p].mu != 1)
	{
		tr[lc].mu *= tr[p].mu % mod;
		tr[lc].mu %= mod;
		tr[lc].add *= tr[p].mu % mod;
		tr[lc].add %= mod;
		tr[lc].sum = (tr[lc].sum * tr[p].mu % mod + tr[lc].add) % mod;
		tr[lc].sum %= mod;
		tr[rc].mu *= tr[p].mu % mod;
		tr[rc].mu %= mod;
		tr[rc].add *= tr[p].mu % mod;
		tr[rc].add %= mod;
		tr[rc].sum = (tr[rc].sum * tr[p].mu % mod + tr[rc].add) % mod;
		tr[lc].sum %= mod;
		tr[p].mu = 1;
	}
}




void push_down(int p) {
	if (tr[p].add!=0||tr[p].mu!=1)
	{
		tr[lc].add = (tr[lc].add *tr[p].mu%mod+ tr[p].add)%mod;
		tr[lc].mu *= tr[p].mu % mod;
		tr[lc].sum = tr[p].mu * tr[lc].sum % mod + tr[p].add * (tr[lc].r - tr[lc].l + 1) % mod;


		tr[rc].add = (tr[rc].add * tr[p].mu % mod + tr[p].add) % mod;
		tr[rc].mu *= tr[p].mu % mod;
		tr[rc].sum = tr[p].mu * tr[rc].sum % mod + tr[p].add * (tr[rc].r - tr[rc].l + 1) % mod;

		tr[p].add = 0;
		tr[p].mu = 1;

	}



}


void pushup(long long int p) {
	tr[p].sum = (tr[lc].sum % mod + tr[rc].sum % mod) % mod;
	tr[p].sum %= mod;
}

//加法懒标记修改法
void add_update(long long int p, long long  int l, long long  int r, long long  int value) {
	if (l <= tr[p].l && r >= tr[p].r)//完全覆盖区间则 修改吧(  忘了?。。。)
	{

		tr[p].add += value % mod;
		tr[p].sum += (tr[p].r - tr[p].l + 1) * value % mod;//要加一哦    //本节点也要修改哦
		tr[p].sum %= mod;
		return;
	}

	//不完全覆盖则分裂
	long long int m = (tr[p].l + tr[p].r) / 2;
	push_down(p);
	if (l <= m)
	{
		add_update(lc, l, r, value);//始终是l和r
	}
	if (r > m)
	{
		add_update(rc, l, r, value);
	}


	//哦~ 懒标记是指从本节点往下不再传递,本节点要修改sum
	pushup(p);  //向上更新

}



void multiply_update(long long int p, long long  int l, long long  int r, long long  int value) {


	if (l <= tr[p].l && r >= tr[p].r)
	{
		tr[p].mu *= value;
		tr[p].mu %= mod;
		if (tr[p].add != 0)
		{
			tr[p].add *= value;
			tr[p].add %= mod;


		}
		tr[p].sum *= value % mod;
		return;
	}
	long long int m = (tr[p].l + tr[p].r) / 2;
	push_down(p);
	if (l <= m)
	{
		multiply_update(lc, l, r, value);
	}
	if (r > m)
	{
		multiply_update(rc, l, r, value);
	}
	pushup(p);  //向上更新

}


long long int query(long long int p, long long  int l, long long  int r) {
	if (l <= tr[p].l && r >= tr[p].r)
	{
		return tr[p].sum % mod;
	}


	push_down(p);

	//pushdown_mu(p);//////似乎很重要,感觉要这么写
	//pushdown(p);////////////


	long long int m = (tr[p].l + tr[p].r) / 2;
	long long int sum = 0;
	if (l <= m)///////???
	{
		sum += query(lc, l, r) % mod;
		sum %= mod;
	}
	if (r > m)
	{
		sum += query(rc, l, r) % mod;
		sum %= mod;
	}
	pushup(p);  //向上更新
	return sum % mod;
}


int main() {
	long long int m;
	long long int n;
	long long int q;
	scanf("%lld", &n);
	getchar();
	scanf("%lld", &q);
	getchar();
	scanf("%lld", &mod);
	getchar();
	for (long long int i = 1; i <= n; i++)
	{
		long long int x;
		scanf("%lld", &x);
		getchar();
		w[i] = x;
	}


	//生成线段树
	build(1, 1, n);






	for (long long int i = 0; i < q; i++)
	{
		int op;
		scanf("%d", &op);
		getchar();


		//加法操作
		if (op == 2)
		{
			long long int x;
			long long int y;
			long long int value;
			scanf("%lld", &x);
			getchar();
			scanf("%lld", &y);
			getchar();
			scanf("%lld", &value);
			getchar();

			add_update(1, x, y, value);


		}

		//乘法操作
		if (op == 1)
		{
			long long int x;
			long long int y;
			long long int value;
			scanf("%lld", &x);
			getchar();
			scanf("%lld", &y);
			getchar();
			scanf("%lld", &value);
			getchar();
			multiply_update(1, x, y, value);
		}

		//查询操作
		if (op == 3)
		{
			long long int x;
			long long int y;
			scanf("%lld", &x);
			getchar();
			scanf("%lld", &y);
			getchar();
			printf("%lld\n", query(1, x, y));
		}

	}


}
2025/2/5 09:32
加载中...