题意。初始X=1;
给n,mod ,表示n次操作
操作1格式 : 1 b 表示用x乘上b
操作2格式: 2 n 表示 当前x除掉第n次 "1操作” 的数
每次操作输出一个答案,输出的答案是要对mod取模
由于有除法所以我们不能每一步取模
一直在想什么办法能过。。。最后卡死了。。
赛后才知道 直接就是一个长度为n的rmq线段树
每个点维护一个数 初始值为1
操作1 就是 修改第i个数为b;
操作2 就是把第对应的数改为1就好了
每次查询 直接查询
对 每次2操作,都要找到长度为1的该区间 修改值为1 然后往上递归修改
所维护的区间里, 长度为1 的区间 也就是画成二叉树后 最底层的区间(仅仅记录一个数) 是不能取模的
其余区间 都可以储存取模后的值(不取模也存不下....)
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <queue>
#include <set>
#include <vector>
#define inf 0x7fffffff
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
const __int64 maxn = 100005;
__int64 mod;
__int64 st_min[maxn<<4] ;
__int64 aa[maxn];
inline __int64 minn(__int64 a,__int64 b) { return a>b?b:a; }
inline __int64 maxx(__int64 a,__int64 b) { return a>b?a:b; }
void PushUP_del(__int64 rt)
{
st_min[rt] = (st_min[rt<<1]*st_min[rt<<1|1])%mod;
}
void PushUP(__int64 rt,__int64 val)
{
st_min[rt] = (st_min[rt<<1]*st_min[rt<<1|1])%mod;
}
__int64 ok=0;
void build(__int64 l,__int64 r,__int64 rt) {
if (l == r)
{ st_min[rt]=1;
return ;
}
__int64 m = (l + r) >> 1;
build(lson);
build(rson);
st_min[rt]=1;
}
void del(__int64 l,__int64 r,__int64 rt,__int64 num,__int64 val)
{
if (l == r&& l==num)
{
st_min[rt]/=val;
return ;
}
__int64 m = (l + r) >> 1;
if (num<=m)
del(lson,num,val);
else
del(rson,num,val);
PushUP_del(rt);
}
void update(__int64 l,__int64 r,__int64 rt,__int64 num,__int64 val)
{
if (l == r&& l==num)
{
st_min[rt]*=val;
return ;
}
__int64 m = (l + r) >> 1;
if (num<=m)
update(lson,num,val);
else
update(rson,num,val);
PushUP(rt,val);
}
__int64 query (__int64 qL,__int64 qR,__int64 l,__int64 r,__int64 rt) //rt是节点编号
{
if (qL <= l && r <= qR) {
return st_min[rt]%mod;
}
__int64 m = (l + r) >> 1;
__int64 ret1 = 1,ret2 = 1;
if (qL <= m) ret1 = query(qL , qR , lson); //复杂情况可直接R<=m作return条件 省时
if (qR > m) ret2 = query(qL , qR , rson);
return (ret1*ret2)%mod;
}
__int64 op_num[100005];
int main()
{
__int64 n ,a,b,i;
__int64 t;
scanf("%I64d",&t);
int cnt=1;
while(t--)
{
scanf("%I64d%I64d",&n,&mod);
__int64 ok=0;
// memset(sum,0,sizeof(sum));
printf("Case #%d:\n",cnt++);
build(1,n,1);
for( i = 1; i <= n; i++)
{
scanf("%I64d %I64d",&a,&b);
op_num[++ok]=b;
if (a==1)
update(1,n,1,i,b);
else
{
del(1,n,1,b,op_num[b]);
}
printf("%I64d\n",query(1,i,1,n,1) );
}
}
return 0;
}

本文探讨了一种使用线段树解决模运算问题的方法,具体包括操作序列处理、线段树构建与更新策略,以及如何通过线段树进行高效查询。重点在于避免每次操作都进行模运算,而是将模运算存储在特定结构中,以提高算法效率。
1733

被折叠的 条评论
为什么被折叠?



