[TJOI2018]数学计算

题目:[TJOI2018]数学计算
小数不能取模
树状数组的tr[p]表示包含a[p](位置p上的元素)的属性和(可能是和、乘..)
树状数组的性质:查前改后

线段树的形:边改边查
区间修改要有懒标记,若每个区间单点修改,它很慢
单点修改可以直接修改 O(lgn),不用懒标记
懒标记就是为区间修改而设计的,表示其子区间的待操作数

线段树就是要考虑维护什么东西
懒标记存什么样的操作数

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int const N=1e5+7;
ll tr[N<<2];
int t,m,mod;
void bulid(int p,int l,int r){
    if(l==r){
        tr[p]=1;return ;
    }
    int mid=(l+r) >> 1;
    bulid(p*2,l,mid);
    bulid(p*2+1,mid+1,r);
    tr[p]=tr[p*2]*tr[p*2+1];
}
void add(int p,int l,int r,int pos,int w){
    if(l==r){
        if(l==pos) tr[p]=w;
        tr[p]%=mod;
        return ;
    }
    int mid=(l+r) >> 1;
    if(pos<=mid) add(p*2,l,mid,pos,w);
    if(mid+1<=pos) add(p*2+1,mid+1,r,pos,w);
    tr[p]=tr[p*2]*tr[p*2+1]; 
    tr[p]%=mod;
}
ll ask(int p,int l,int r,int x,int y){
    if(x<=l&&r<=y) return tr[p];
    int mid=(l+r) >> 1;
    ll res=1;
    if(x<=mid) res*=ask(p*2,l,mid,x,y);
    if(mid+1<=y) res*=ask(p*2+1,mid+1,r,x,y);
    return res;
}
int main(){
    cin >> t;
    while(t--){
        cin >> m >> mod;
        bulid(1,1,m);
        int op,x;
        for(int i=1;i<=m;++i){
            cin >> op >> x;
            if(op==1){
                add(1,1,m,i,x);
                //cout << ask(1,1,m,1,i)%mod << "\n";
                cout << tr[1] << "\n";
            }
            else {
                add(1,1,m,x,1);
                //cout << ask(1,1,m,1,i)%mod << "\n";
                cout << tr[1] << "\n";
            }
        }  
    }
    return 0;
}
线段树和数状数组经典例题 文章被收录于专栏

线段树和数状数组经典例题

全部评论

相关推荐

06-01 21:50
已编辑
天津理工大学 Java
点赞 评论 收藏
分享
06-11 14:15
已编辑
门头沟学院 后端
田心今心:打招呼改一下,把实习半年以上随时到岗放第一行,因为ssob的hr不点击看的时候只能看前面几个字,你前面几个字hr获取不到什么信息,也就不会点进来看
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务