bzoj 5334 数学计算

bzoj 5334 数学计算

  • 开始想直接模拟过程做,但模数 \(M\) 不一定为质数,若没有逆元就 \(fAKe\) 掉了.
  • 注意到操作 \(2\) 是删除对应的操作 \(1\) ,相当于只有 \(1\) 操作,但每个操作有一个生效的时限.
  • 将所有操作离线下来,用一颗线段树维护每个时间的答案.对于操作 \(1\) ,预处理出生效的时限后,区间修改那一段即可.注意有没有删除的情况,右端点设为 \(Q\) .
  • 预处理结束后,对每个操作可以一边改一边做,后面的操作显然不会对这里的答案造成影响.
  • 时间复杂度为 \(O(QlogQ)\) .

原来这东西是叫线段树分治.之前我就叫做是离线后线段树上乱搞...

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mp make_pair
#define pii pair<int,int>
inline int read()
{
    int out=0,sgn=1;
    char jp=getchar();
    while(jp!='-' && (jp<'0' || jp>'9'))
        jp=getchar();
    if(jp=='-')
        sgn=-1,jp=getchar();
    while(jp>='0' && jp<='9')
        out=out*10+jp-'0',jp=getchar();
    return out*sgn;
}
const int MAXN=1e5+10;
int Q,P;
inline int mul(int a,int b)
{
    return 1LL * a * b % P;
}
int fpow(int a,int b)
{
    int res=1;
    while(b)
        {
            if(b&1)
                res=mul(res,a);
            a=mul(a,a);
            b>>=1;
        }
    return res%P;
}
struct query{
    int op,m,r;
}q[MAXN];
namespace SEG{
    struct node{
        int l,r;
        int prod,tag;
    }Tree[MAXN<<2];
    #define root Tree[o]
    #define lson Tree[o<<1]
    #define rson Tree[o<<1|1]
    void BuildTree(int o,int l,int r)
        {
            root.l=l,root.r=r;
            root.prod=1,root.tag=1;
            if(l==r)
                return;
            int mid=(l+r)>>1;
            BuildTree(o<<1,l,mid);
            BuildTree(o<<1|1,mid+1,r);
        }
    void Modifiy(int o,int v)
        {
            root.prod=mul(root.prod,v);
            root.tag=mul(root.tag,v);
        }
    void pushdown(int o)
        {
            if(root.tag!=1)
                {
                    Modifiy(o<<1,root.tag);
                    Modifiy(o<<1|1,root.tag);
                    root.tag=1;
                }
        }
    void update(int o,int L,int R,int v)
        {
            int l=root.l,r=root.r;
            if(l>R || L>r)
                return;
            if(L<=l && r<=R)
                {
                    Modifiy(o,v);
                    return;
                }
            pushdown(o);
            update(o<<1,L,R,v);
            update(o<<1|1,L,R,v);
        }
    int query(int o,int pos)
        {
            int l=root.l,r=root.r;
            if(l==r)
                return root.prod;
            if(pos<l || pos>r)
                return 1;
            int mid=(l+r)>>1;
            pushdown(o);
            if(pos<=mid)
                return query(o<<1,pos);
            else
                return query(o<<1|1,pos);
        }
}
int main()
{
    int T=read();
    while(T--)
        {
            Q=read(),P=read();
            for(int i=1;i<=Q;++i)
                {
                    int op=read();
                    q[i].op=op;
                    if(op==1)
                        q[i].m=read(),q[i].r=Q+1;
                    else
                        {
                            int pos=read();
                            q[pos].r=i;
                        }
                }
            SEG::BuildTree(1,1,Q);
            for(int i=1;i<=Q;++i)
                {
                    if(q[i].op==1)
                        {
                            int l=i,r=q[i].r;
                            SEG::update(1,l,r-1,q[i].m);
                            int ans=SEG::query(1,l);
                            printf("%d\n",ans);
                        }
                    else
                        {
                            int ans=SEG::query(1,i);
                            printf("%d\n",ans);
                        }
                }
        }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/jklover/p/10448242.html