zoukankan      html  css  js  c++  java
  • HDU 5475 An easy problem(线段树)

    题目链接:

                 戳我

    题目大意:

    一个计算器只有两种运算,初始化 X = 1

    第一种操作: X 乘以 一个数,获得新的 X

    第二种操作: 当前的 X 除以 一个数

    输出  X % M

    其中 1 y 表示第一种操作,即 X  = X * y

    2 n 表示 X 除以 前面的 第 n 个操作的那个 y,保证 第 n 个表示的是 1,即数据合法

    注意:X 在进行操作的时候不要除模, 而是输出的时候除模,即要保证 X 进行操作的时候除模是和不除模情况下是相等的。

    比如:

    3 10

    1 5

    1 3

    2 1,如果边运算边除模,最后的答案是 5, 5,  0, 但是正确答案是 (1*5)%10,(1*5*3)%10, (1*5*3 / 5) % 10。 

    样例解释:

    1 // 测试样例组数

    10 1000000000 // 10个操作,M

    1 2   // 1 * 2 = 2

    2 1    // 1 * 2 / 2 = 1  除以第一个操作是 1 

    1 2    // 1 * 2 = 2

    1 10   // 2 * 10 = 20

    2 3    // 20 / 2 = 10 

    2 4

    1 6

    1 7

    1 12

    2  7

    解题思路:

    最开始的想法肯定是暴力。把每次操作都记下来,乘法就是 从第一个数 边乘 边取模输出。除法就是把 相应的前面的数变为 1 即可,在从第一个数  边乘边取模。

    但无意 是TLE。

    我的做法是 用 线段树来做。线段树的节点保存 这个区间 所有数相乘 取模 后的值。

    且线段树 初始化全为 1 ,乘法就把相应的 值 改为 y,除法就把相应的 值 改为 1

    每次询问 都输出 tree[1].num  即可, 要注意 long long 哟

    参考代码:

    #include <stdio.h>
    #include <iostream>
    #include <string.h>
    using namespace std;
     
    #define manx 100005
    struct Tree
    {
        int left;
        int right;
        long long num; //该区间内,已经出现的个数
    }tree[4 * manx];
    int a[manx], n, m;
     
    void BuildTree(int i, int l, int r);
    void Update(int i, int id, int val);
    int Query(int i, int l, int r);
     
    int main()
    {
        int T, x, y;
        scanf("%d", &T);
        for(int tt = 1; tt <= T; tt++)
        {
            scanf("%d %d", &n, &m);
            BuildTree(1, 1, n);
            printf("Case #%d:
    ", tt);
            for(int i = 1; i <= n; i++)
            {
                scanf("%d %d", &x, &y);
                if(x == 1)
                {
                    Update(1, i, y);
                    printf("%lld
    ", tree[1].num);
                }
                else
                {
                    Update(1, y, 1);
                    printf("%lld
    ", tree[1].num);
                }
            }
        }
        return 0;
    }
     
    void BuildTree(int i, int l, int r)//建树
    {
        tree[i].left = l;
        tree[i].right = r;
        tree[i].num = 1;//初始化全部为0,因为还没有输入
        if(tree[i].left == tree[i].right) return;
        int mid = (l + r) >> 1;
        BuildTree(i << 1, l, mid);
        BuildTree(i << 1 | 1, mid + 1, r);
    }
     
    void Update(int i, int id, int val)//更新
    {
        if(tree[i].left == id && tree[i].right == id)
        {
            tree[i].num = val;//输入过了,标记为1
            return;
        }
        int mid = (tree[i].left + tree[i].right) >> 1;
        if(id > mid)  Update(i << 1 | 1, id, val);
        else   Update(i << 1, id, val);
        tree[i].num = (tree[i << 1].num * tree[i << 1 | 1].num) % m;//更新此区间内,已经出现过的总数
    }
    

      

  • 相关阅读:
    迭代是人,递归是神(迭代与递归的总结:比较)
    HMM(隐马尔科夫)用于中文分词
    Python 字典(Dictionary) get()方法
    jieba中文分词源码分析(四)
    一个隐马尔科夫模型的应用实例:中文分词
    小白给小白详解维特比算法(二)
    IOS 播放音频流媒体
    iOS开发之多媒体API(1)
    IOS流媒体播放
    ios7中使用scrollview来横向滑动图片,自动产生偏移竖向的偏移 问题
  • 原文地址:https://www.cnblogs.com/tenlee/p/4842970.html
Copyright © 2011-2022 走看看