数学计算

P4588 [TJOI2018] 数学计算

考虑将所有 \(1\) 操作涉及到的数存入线段树中,初始为 \(1\)

1操作:在某个位置修改为某个值。

2操作:在某个位置修改为 \(1\)

查询:查询所有数的乘积。

无需懒标记,可以直接将所有操作数按照下标丢进去,也可以先提取出操作1(线段树的大小会小一些)。

直接做

#include<cstdio>
using namespace std;
#define Ed for(int i=h[x];~i;i=ne[i])
#define Ls(i,l,r) for(int i=l;i<r;++i)
#define Rs(i,l,r) for(int i=l;i>r;--i)
#define Le(i,l,r) for(int i=l;i<=r;++i)
#define Re(i,l,r) for(int i=l;i>=r;--i)
#define L(i,l) for(int i=0;i<l;++i)
#define E(i,l) for(int i=1;i<=l;++i)
#define W(t) while(t--)
#define Wh while
#define ls p<<1
#define rs p<<1|1
const int N=100010,M=4*N;
int T,m,v[M],l[M],r[M];
#define pushup v[p]=1ll*v[ls]*v[rs]%m
void build(int p,int L,int R){
    l[p]=L,r[p]=R,v[p]=1;
    if(L==R)return;
    int mid=L+R>>1;
    build(ls,L,mid);
    build(rs,mid+1,R);
}
void update(int p,int x,int vv){
    if(l[p]==r[p]){
        v[p]=vv;
        return;
    }
    int mid=l[p]+r[p]>>1;
    if(x<=mid)update(ls,x,vv);
    else update(rs,x,vv);
    pushup;
}
void solve(){
    int n;
    scanf("%d%d",&n,&m);
    build(1,1,n);
    E(i, n){
        int op,w;
        scanf("%d%d",&op,&w);
        if(op==1)update(1,i,w);
        else update(1,w,1);
        printf("%d\n",v[1]);
    }
}
int main(){
    #ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    #endif
    scanf("%d",&T);
    W(T)solve();
    return 0;
}

提取操作1再做

#include<cstdio>
using namespace std;
#define Ed for(int i=h[x];~i;i=ne[i])
#define Ls(i,l,r) for(int i=l;i<r;++i)
#define Rs(i,l,r) for(int i=l;i>r;--i)
#define Le(i,l,r) for(int i=l;i<=r;++i)
#define Re(i,l,r) for(int i=l;i>=r;--i)
#define L(i,l) for(int i=0;i<l;++i)
#define E(i,l) for(int i=1;i<=l;++i)
#define W(t) while(t--)
#define Wh while
#define ls p<<1
#define rs p<<1|1
const int N=100010,M=4*N;
int T,a[N],m,op[N],w[N],id[N],k,v[M],l[M],r[M];
#define pushup v[p]=1ll*v[ls]*v[rs]%m
void build(int p,int L,int R){
    l[p]=L,r[p]=R,v[p]=1;
    if(L==R)return;
    int mid=L+R>>1;
    build(ls,L,mid);
    build(rs,mid+1,R);
}
void update(int p,int x,int vv){
    if(l[p]==r[p]){
        v[p]=vv;
        return;
    }
    int mid=l[p]+r[p]>>1;
    if(x<=mid)update(ls,x,vv);
    else update(rs,x,vv);
    pushup;
}
void solve(){
    k=0;
    int n;
    scanf("%d%d",&n,&m);
    E(i, n){
        scanf("%d%d",op+i,w+i);
        if(op[i]==1)id[i]=++k;
    }
    build(1,1,k);
    E(i, n){
        if(op[i]==1)update(1,id[i],w[i]);
        else update(1,id[w[i]],1);
        printf("%d\n",v[1]);
    }
}
int main(){
    #ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    #endif
    scanf("%d",&T);
    W(T)solve();
    return 0;
}

二者时间、空间、代码复杂度上各有优势,任意选择。

posted @ 2023-09-26 13:29  wscqwq  阅读(5)  评论(0编辑  收藏  举报