無名線段樹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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章