루오 구 문제 용액 [P4588] TJOI2018] 수학

제목 설명

팥의 한 곳 \는 (X \) , 초기 값 (\ 1 \) 팥 A의 콩. \ (Q \) 연산 동작의 두 가지 종류가있다 :

\. (1 \; m의 \) \ (X = X \ 시간 m \) 출력 \ (X \ MOD % \) ;

\ (2 \; POS \) \ (X = X / \)\ (POS \) 동작의 횟수 (보증 승산 \ (POS \) 특정 타입에 작업 \ (1 \) 각각에 대해, 형태 (\ 1 \) 동작은 최대 하나의 다른) 출력하는 것 \ (X \ MOD % \) ;

입력 형식

\ (T \) 의 입력 설정 ( \ (T \ leq5 \) );

입력 된 각각의 세트의 경우, 첫 번째 행은 두 자리 \ (Q, MOD \) ( \ (Q \의 leq100000, MOD \ leq100000000 \) );

다음 \ (Q \) 행, 각 행위 조작 형 \ (OP \) , 동작 또는 승산 번째 \ (m의 \)는 (모든 입력이 유효한지 확인하기 위해).

출력 형식

동작의 실행에있어서 각 동작 출력 선에 대해서는 \을 (X % \ 개조 \)

샘플 입출력

입력 # 1

1
10 1000000000
1 2
2 1
1 2
1 10
2 3
2 4
1 6
1 7
1 12
2 7

출력 # 1

2
1
2
20
10
1
6
42
504
84

설명 / 팁

\ (20 \ %의 \) 데이터, \. (1 \ 당량 Q \ leq500 \)

옵션 (\ 100 \ %의 \) 데이터, \. (1 \ 당량 Q \ leq100000 \)

문제 해결

이 질문은 사고 어렵다, 얼마나 어려운 목선 생각합니다.

폭력 시뮬레이션 생각하기 쉬운, 그러나,이 질문에서 폭력 시뮬레이션은 잘못입니다! ! !

세트 \ (\ texttt {해킹} \ ) 데이터 :

1
2 10
1 99
2 99

출력해야한다 :

9
1

...... ~~ 당신이 정밀하게 할 수있는 것 같은데,하지만 공간적 복잡도는 접촉

바로 여기에 긍정적 인 솔루션을 말한다.

제품 부 세그먼트 트리 유지 보수 작업은, 만약 \ (1 \) 현재 노드 동작의 값을 변경한다 (m의 \) \ \ (2 \)을 또한 연산의 수가 넣을 위치 노드의 값을 대신 \ (1 \) .

출력 값은 출력 라인 ...... 루트 노드를 지시 할 수있다.

코드

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#define int long long//注意long long
#define itn int
#define gI gi

using namespace std;

inline int gi()//快读
{
    int f = 1, x = 0; char c = getchar();
    while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
    while (c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = getchar();}
    return f * x;
}

int t, q, mod, tr[400003], ans;

inline int ls(int p) {return p << 1;}//左儿子
inline int rs(itn p) {return p << 1 | 1;}//右儿子

void modify(int ql, int qr, int z, int l, int r, int p)//修改节点
{
    if (l == r && l == ql) {tr[p] = z; return;}//到了叶子节点进行修改
    int mid = (l + r) >> 1;
    if (ql <= mid) modify(ql, qr, z, l, mid, ls(p));//递归左子树
    if (qr > mid) modify(ql, qr, z, mid + 1, r, rs(p));//递归右子树
    tr[p] = (tr[ls(p)] % mod * tr[rs(p)] % mod) % mod;//上传节点
    return;
}

signed main()
{
    t = gi();
    while (t--)
    {
        q = gi(), mod = gi();
        for (int i = 1; i <= 400001; i+=1) tr[i] = 1;//注意,本题中不需要建树,只需要把所有节点的值设为1
        for (int i = 1; i <= q; i+=1)
        {
            int op = gi(), m = gi();
            if (op == 1) modify(i, i, m, 1, q, 1);//操作1,将第i个点的值修改为m
            else modify(m, m, 1, 1, q, 1);//操作2,将第m个点的值修改为1
            printf("%lld\n", tr[1]);//输出
        }
    }
    return 0;
}

추천

출처www.cnblogs.com/xsl19/p/11617062.html