链接:https://www.nowcoder.com/acm/contest/136/F
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
HA实验是一个生产、提炼“神力水晶”的秘密军事基地,神力水晶可以让机器的工作效率成倍提升。
HA实验基地有n台发电机,标号为1-n,每台发电机的发电效率为1。
为了满足基地的用电需求,HtBest会在某台发电机上镶嵌一个等级为i的神力水晶,该发电机的发电效率是镶嵌神力水晶之前的i倍,一个发电机可以同时镶嵌多个神力水晶。
但是神力水晶有时还有别的用处,HtBest会拆掉某台发电机之前镶嵌上的一个神力水晶(设等级为i),发电机效率降为拆掉神力水晶前的1/i。
HtBest有时想知道第l到r台发电机的总发电效率为多少。
输入描述:
第一行有2个正整数n,m,分别表示发电机数量和操作数。 接下来m行,每行有3个正整数,x, y, z。 x=1时,HtBest镶嵌为第y台发电机镶嵌了一个等级为z的神力水晶, x=2时,HtBest为第y台发电机拆掉了一个等级为z的神力水晶, x=3时,HtBest想知道[y,z]的发电机效率的乘积。
输出描述:
对于每个x=3的操作,输出一行,表示[y,z]的发电机的效率的乘积。 由于输出过大,你需要对输出结果模1000000007(1e9+7)。
示例1
输入
4 4 1 2 3 3 1 4 2 2 3 3 1 4
输出
3 1
说明
操作1之后,每台发电机效率:1 3 1 1 操作3之后,每台发电机效率:1 1 1 1
示例2
输入
4 4 1 2 2 1 2 3 1 3 4 3 1 4
输出
24
说明
操作1之后,每台发电机效率:1 2 1 1 操作2之后,每台发电机效率:1 6 1 1 操作3之后,每台发电机效率:1 6 4 1
备注:
对于100%的测试数据: 1 ≤ n, m ≤ 1000000 1 ≤ 神力水晶等级 ≤ 100000 数据量较大,注意使用更快的输入输出方式。
思路:这题数据范围过大,每一个水晶的能量有可能会很大,因此在移除水晶的时候,需要使用到逆元取模,其余都是线段树模板。
code:
#include<cstdio>
#define N 1000010
#define MOD 1000000007
typedef long long ll;
struct n{
ll val;
int left, right;
}Tree[4 * N];
int Elec[N];
void createTree(int root, int l, int r){
if(l == r){
Tree[root].val = Elec[l];
return;
}
int mid = (l + r) >> 1;
createTree(root << 1, l, mid);
createTree(root << 1 | 1, mid + 1, r);
Tree[root].val = (Tree[root << 1].val * Tree[root << 1 | 1].val) % MOD;
}
ll search(int root, int ml, int mr, int l, int r){
if(l > mr || r < ml){
return 1;
}
if(l <= ml && r >= mr){
return Tree[root].val % MOD;
}
int mid = (ml + mr) >> 1;
return (search(root << 1, ml, mid, l, r) * search(root << 1 | 1, mid + 1, mr, l, r)) % MOD;
}
void updateMul(int root, int l, int r, int index, int val){
if(l == r){
if(index == l){
Tree[root].val *= val;
Tree[root].val %= MOD;
}
return;
}
int mid = (l + r) >> 1;
if(index <= mid){
updateMul(root << 1, l, mid, index, val);
}else{
updateMul(root << 1 | 1, mid + 1, r, index, val);
}
Tree[root].val = (Tree[root << 1].val * Tree[root << 1 | 1].val) % MOD;
}
ll inverse(int val){
ll n = MOD - 2;
ll base = val;
ll res = 1;
while(n){
if(n & 1){
res = (res * base) % MOD;
}
n >>= 1;
base = (base * base) % MOD;
}
return res;
}
void updateDiv(int root, int l, int r, int index, int val){
if(l == r){
if(index == l){
Tree[root].val *= inverse(val);
Tree[root].val %= MOD;
}
return;
}
int mid = (l + r) >> 1;
if(index <= mid){
updateDiv(root << 1, l, mid, index, val);
}else{
updateDiv(root << 1 | 1, mid + 1, r, index, val);
}
Tree[root].val = (Tree[root << 1].val * Tree[root << 1 | 1].val) % MOD ;
}
int main(){
int n, m;
scanf("%d %d", &n, &m);
for(int i = 1;i <= n;i++){
Elec[i] = 1;
}
createTree(1, 1, n);
for(int i = 0;i < m;i++){
int x, y, z;
scanf("%d %d %d", &x, &y, &z);
if(x == 1){
updateMul(1, 1, n, y, z);
}else if(x == 2){
updateDiv(1, 1, n, y, z);
}else if(x == 3){
ll res = search(1, 1, n, y, z);
printf("%lld\n", res);
}
}
return 0;
}