无名线段树2

题目大意:

维护一个算式,,每次询问一个x带入算式的值是多少,从左到右计算,计算有三种:’+’,’*’,’^’,例子如下:

    算式为 +2 *3 ^2 +4

    X=3时,Ans=((3+2)*3)^2+4=229.

    X=2时,Ans=((2+2)*3)^2+4=148.

支持这两种操作:

    1:询问x带入算式的值。

    2:将第k个地方的计算符号改变。

    (n<=50000,m<=50000,输入的所有数小于29393,n为计算符号数,m为操作数)。

答案Mod 29393 输出。

 

题解:毕姥爷又玩模数….

29393=7*13*17*19….在学了中国剩余定理之前根本不知道这代表什么2333.

然后就比较简单了,我们维护4棵线段树,每一个分别代表Mod(7,13,17,19)的答案。

因为模数很小,所以说我们线段树直接暴力即可,val[x][i][j]表示在第j个模数的模意义下的线段树上,输入i,经过当前节点x及其子树的所有运算之后,输出的值,这个暴力维护即可,每棵每次操作复杂度为Mod*log。

然后如果查询x,我们分别在四棵线段树的顶点1查询输入x之后得到的值,一共4个,然后中国剩余定理合并这四个解就可以了。

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <string>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <ctime>
using namespace std;
int M[5],t[5],flag[100010],A[100010],Point[5];
int n,m,a,pos,Ans;
int getint() {
	char c = 'd';
	int ret = 0;
	while(c < '0' || c > '9') c = getchar();
	while(c >= '0' && c <= '9') ret = ret * 10 + c - '0',c = getchar();
	return ret;
}
int ksm(int x,int y,int Mod) {
	int ret = 1;
	x %= Mod;
	for(int i = y;i > 0;i >>= 1) {
		ret *= (i % 2 == 1) ? x:1;
		ret %= Mod;
		x = (x * x) % Mod; 
	}
	return ret;
}
void prework() {
	M[1] = 13 * 17 * 19;
	M[2] = 7 * 17 * 19;
	M[3] = 7 * 13 * 19;
	M[4] = 7 * 13 * 17;
	t[1] = ksm(M[1],5,7);
	t[2] = ksm(M[2],11,13);
	t[3] = ksm(M[3],15,17);
	t[4] = ksm(M[4],17,19);
}
struct Segment_Tree {
	int Prime[5],val[400010][5][20];
	Segment_Tree () {
		Prime[1] = 7;
		Prime[2] = 13;
		Prime[3] = 17;
		Prime[4] = 19;
	}
	void build(int Now,int l,int r,int k) {
		if(l == r) {
			if(flag[r] == 1) {
				for(int i = 0;i <= Prime[k] - 1;i ++) {
					val[Now][k][i] = (i + A[r]) % Prime[k];
				}
			}
			if(flag[r] == 2) {
				for(int i = 0;i <= Prime[k] - 1;i ++) {
					val[Now][k][i] = (i * A[r]) % Prime[k];
				}
			}
			if(flag[r] == 3) {
				for(int i = 0;i <= Prime[k] - 1;i ++) {
					val[Now][k][i] = ksm(i,A[r],Prime[k]) % Prime[k];
				}
			}
			return ;
		}
		int Mid = (l + r) >> 1;
		build(Now << 1,l,Mid,k);
		build(Now << 1 | 1,Mid+1,r,k);
		for(int i = 0;i <= Prime[k] - 1;i ++) {
			int p = val[Now << 1][k][i]; 
			val[Now][k][i] = val[Now << 1 | 1][k][p];
		}
		return ;
	}
	void insert(int Now,int l,int r,int k,int x) {
		if(l == r) {
			if(flag[r] == 1) {
				for(int i = 0;i <= Prime[k] - 1;i ++) {
					val[Now][k][i] = (i + A[r]) % Prime[k];
				}
			}
			if(flag[r] == 2) {
				for(int i = 0;i <= Prime[k] - 1;i ++) {
					val[Now][k][i] = (i * A[r]) % Prime[k];
				}
			}
			if(flag[r] == 3) {
				for(int i = 0;i <= Prime[k] - 1;i ++) {
					val[Now][k][i] = ksm(i,A[r],Prime[k]) % Prime[k];
				}
			}
			return ;
		}
		int Mid = (l + r) >> 1;
		if(x <= Mid) insert(Now << 1,l,Mid,k,x);
		if(x > Mid) insert(Now << 1 | 1,Mid+1,r,k,x);
		for(int i = 0;i <= Prime[k] - 1;i ++) {
			int p = val[Now << 1][k][i]; 
			val[Now][k][i] = val[Now << 1 | 1][k][p];
		}
		return ;
	}
	int Ask(int Now,int l,int r,int k,int x) {
		int ret = val[Now][k][x];
		return ret;
	}
};Segment_Tree T;
int Merge() {
	int ret = 0;
	for(int i = 1;i <= 4;i ++) {
		ret += Point[i] * M[i] * t[i];
		ret %= (7 * 13 * 17 * 19);
	}
	return ret;
}
int main() {
	//freopen("calculator.in","r",stdin);
	//freopen("calculator.out","w",stdout);
	prework();
	n = getint();
	m = getint();
	for(int i = 1;i <= n;i ++) {
		char c = 'd';
		while(c != '*' && c != '^' && c != '+') c = getchar();
		a = getint();
		if(c == '+') flag[i] = 1,A[i] = a;
		else if(c == '*') flag[i] = 2,A[i] = a;
		else if(c == '^') flag[i] = 3,A[i] = a; 
	}
	T.build(1,1,n,1);
	T.build(1,1,n,2);
	T.build(1,1,n,3);
	T.build(1,1,n,4);
	for(int i = 1;i <= m;i ++) {
		int mp = 0;
		mp = getint();
		if(mp == 1) {
			a = getint();
			Point[1] = T.Ask(1,1,n,1,a % 7);
			Point[2] = T.Ask(1,1,n,2,a % 13);
			Point[3] = T.Ask(1,1,n,3,a % 17);
			Point[4] = T.Ask(1,1,n,4,a % 19);
			Ans = Merge();
			printf("%d\n", Ans );
		}
		if(mp == 2) {
			pos = getint();
			char c = 'd';
		    while(c != '*' && c != '^' && c != '+') c = getchar();
		    a = getint();
		    if(pos == 0) pos = 1;
		    if(c == '+') flag[pos] = 1,A[pos] = a;
		    else if(c == '*') flag[pos] = 2,A[pos] = a;
		    else if(c == '^') flag[pos] = 3,A[pos] = a; 
			T.insert(1,1,n,1,pos);
			T.insert(1,1,n,2,pos);
			T.insert(1,1,n,3,pos);
			T.insert(1,1,n,4,pos);
		}
	}
	return 0;
}


1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、下载 4使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、 4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.m或d论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 、1资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值