题解:P7334 [JRKSJ R1] 吊打

· · 题解

一道序列题,我用了延迟修改操作。

首先思考一下查询之间的关系。

注意到在平方后又出现了开方的话这两可以抵消。这样子之后的修改序列变成一堆根号后和一堆平方。

注意到 5 个开方就能让任何数变成 1,多个平方用神秘数学推导就能用快速幂解决。

#include<bits/stdc++.h>
#define int long long
#define ls o<<1
#define rs o<<1|1
using namespace std;
const int N=2e5+5,P=998244353;
int nxt[N],a[N],ans;
struct st{
    int opt,k;
};
vector < st > vec[N<<2];
char c[N];
inline int min(int x,int y){
    return x>y?y:x;
}
inline void pushin(int o,int opt,int k){
    if (opt==1){//刚开始想复杂了用了vector ...
        if (vec[o].empty()){
            vec[o].push_back({1,k});
        }else if(vec[o].back().opt==2){
            if (vec[o].back().k>=k){
                vec[o].back().k-=k;
                if (vec[o].back().k==0) vec[o].pop_back();
            }else{
                k-=vec[o].back().k;
                vec[o].pop_back();
                pushin(o,1,k);
            }
        }else if (vec[o].back().opt==1) vec[o].back().k+=k;
    }else if(opt==2){
        if (vec[o].empty()||vec[o].back().opt==1) vec[o].push_back({2,k});
        else if(vec[o].back().opt==2) vec[o].back().k+=k;
    }
}
inline void pushdown(int o){
    for (auto x:vec[o]){
        pushin(ls,x.opt,x.k);
        pushin(rs,x.opt,x.k);
    }
    vec[o].clear();
    return ;
}
inline void change(int l,int r,int x,int y,int opt,int o){
    if (x<=l&&r<=y){
        pushin(o,opt,1);
        return ;
    }
    pushdown(o);
    int mid=(l+r)>>1;
    if (x<=mid) change(l,mid,x,y,opt,ls);
    if (y>mid) change(mid+1,r,x,y,opt,rs);
    return ;
}
inline int qpow(int x,int k,int p){
    int ret=1;
    while (k){
        if (k&1) ret=ret*x%p;
        x=x*x%p,k>>=1;
    }
    return ret;
}
inline int get(int x,int opt,int k){
    if (opt==1){
        while (k--){
            x=sqrt(x);
            if (x==1) return 1;
        }
        return x;
    }
    if (opt==2) return qpow(x,qpow(2,k,P-1),P);//x^(2^k)%P=x^((2^k)%(P-1))%P
    return 0;
}
inline void getans(int l,int r,int o){
    if (l==r){
        int x=a[l];
        for (auto qwq:vec[o]) x=get(x,qwq.opt,qwq.k);
        ans+=x,ans%=P;
        return ;
    }
    int mid=(l+r)>>1;
    pushdown(o);
    getans(l,mid,ls);
    getans(mid+1,r,rs);
}
signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int n,q;cin>>n>>q;
    for (int i=1;i<=n;i++) cin>>a[i];
    while (q--){
        int opt,x,y;cin>>opt>>x>>y;
        change(1,n,x,y,opt,1);
    }
    getans(1,n,1);
    cout<<ans;
    return 0;
}