hdu5475An easy problem 线段树

//两个操作
//初始数值是x = 1
//1 y 将 x = x*y%m
//2 n x = (x*a[n])%m a[n]为第n个数
//每次输出对应的x
//先离线,然后用线段树每个数作用的区间都乘以该数
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std ;
const int maxn = 1e5+10;
#define left v<<1
#define right v<<1|1
typedef long long ll  ;
struct node
{
    int l , r ;
    ll lazy ;
}tree[maxn<<2] ;
ll m ;
int vis[maxn] ;
ll a[maxn] ;
void push_down(int v)
{
    tree[left].lazy = (tree[v].lazy*tree[left].lazy)%m ;
    tree[right].lazy = (tree[v].lazy*tree[right].lazy)%m ;
    tree[v].lazy = 1 ;
}
void build(int l , int r  , int v)
{
    tree[v].l = l ;
    tree[v].r = r ;
    tree[v].lazy = 1 ;
    if(l == r)return ;
    int mid = (l + r) >> 1 ;
    build(l , mid , left) ;
    build(mid+1 , r , right) ;
}
void update(int l , int r , int v , ll x)
{
    if(l <= tree[v].l && tree[v].r <= r)
    {
        tree[v].lazy = (tree[v].lazy*x)%m ;
        return   ;
    }
    push_down(v) ;
    int mid = (tree[v].l + tree[v].r) >> 1 ;
    if(l <= mid)update(l , r , left , x) ;
    if(r > mid)update(l , r , right , x) ;
}
ll query(int p , int v)
{
    if(tree[v].l == tree[v].r)
    return tree[v].lazy%m ;
    push_down(v) ;
    int mid = (tree[v].l + tree[v].r) >> 1 ;
    if(p <= mid)return query(p , left) ;
    else return query(p , right) ;
}
int main()
{
    int t ;
    int cas  = 0 ;
    scanf("%d" , &t) ;
    while(t--)
    {
        int q  ;
        scanf("%d%lld" , &q , &m) ;
        memset(vis , 0 , sizeof(vis)) ;
        build(1 , q , 1) ;
        for(int i = 1;i <= q;i++)
        {
            int x , y ;
            scanf("%d%d" , &x , &y) ;
            if(x == 2)
            {
                update(y , i-1  , 1 , a[y]) ;
                vis[i] = vis[y] = 1 ;
            }
            else a[i] = (ll)y ;
        }
        for(int i = 1;i <= q;i++)
        if(!vis[i])
        update(i , q , 1 , a[i]) ;
        printf("Case #%d:\n" , ++cas) ;
        for(int i = 1;i <= q;i++)
        printf("%lld\n" , query(i , 1)) ;
    }
    return  0;
}


你可能感兴趣的:(线段树)