HDU 3074 Multiply game(线段树)

单点更新,更新时先除去 原来的数,因为有去摸,可以用乘上逆元代替。

//============================================================================
// Name        : A.cpp
// Author      : L_Ecry
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#define N 50050
#define MOD 1000000007
#define LL long long
using namespace std;
LL value[N*4];
int a[N];
int n;
int extgcd(int a,int b,int &x,int &y)
{
    int t,d;
    if(b==0){
        x=1;y=0;
        return a;
    }
    d=extgcd(b,a%b,x,y);
    t=x;
    x=y;
    y=t-a/b*y;
    return d;
}
int invmod(int a,int n)
{
    int x,y;
    if(extgcd(a,n,x,y)!=1)return -1;
    return (x%n+n)%n;
}
void build(int l,int r,int i)
{
    if(l==r){
        value[i]=a[l];
        return;
    }
    int mid=(l+r)>>1;
    int lson=(i<<1),rson=(i<<1|1);
    build(l,mid,lson);
    build(mid+1,r,rson);
    value[i]=(value[lson]*value[rson])%MOD;
}
void update(int l,int r,int p,int va,int i)
{
    if(l==r)
    {
        value[i]=va;
        return;
    }
    value[i]=(value[i]*invmod(a[p],MOD))%MOD;
    value[i]=(value[i]*va)%MOD;
    int mid=(l+r)>>1;
    if(p<=mid)update(l,mid,p,va,i<<1);
    else update(mid+1,r,p,va,i<<1|1);
}
LL query(int l,int r,int pl,int pr,int i)
{
    if(l==pl&&r==pr)
        return value[i];
    int mid=(l+r)>>1;
    if(mid>=pr)return query(l,mid,pl,pr,i<<1);
    else if(pl>mid)return query(mid+1,r,pl,pr,i<<1|1);
    else {
        return (query(l,mid,pl,mid,i<<1)*query(mid+1,r,mid+1,pr,i<<1|1))%MOD;
    }
}
void init()
{
    scanf("%d",&n);
    for(int i=1;i<=n;++i)
        scanf("%d",&a[i]);
    build(1,n,1);
}
void solve()
{
    int q;
    scanf("%d",&q);
    while(q--)
    {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        if(x==1)
        {
            update(1,n,y,z,1);
            a[y]=z;
        }else
        {
            printf("%lld\n",query(1,n,y,z,1));
        }
    }
}
int main() {
    int tt;
    scanf("%d",&tt);
    while(tt--)
    {
        init();
        solve();
    }
    return 0;
}

HDU 3074 Multiply game(线段树)

时间: 2024-12-30 05:09:42

HDU 3074 Multiply game(线段树)的相关文章

HDU 3074-Multiply game(线段树:单点更新,区间求积)

Multiply game Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1450    Accepted Submission(s): 508 Problem Description Tired of playing computer games, alpc23 is planning to play a game on numbe

HDU 4902 Nice boat(线段树)

HDU Nice boat 题目链接 题意:给定一个序列,两种操作,把一段变成x,把一段每个数字,如果他大于x,就变成他和x的gcd,求变换完后,最后的序列. 思路:线段树,每个结点多一个cover表示该位置以下区间是否数字全相同,然后每次延迟操作,最后输出的时候单点查询即可 代码: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N = 1

hdu 2795 Billboard(线段树)

Billboard Time Limit: 20000/8000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 10890    Accepted Submission(s): 4827 Problem Description At the entrance to the university, there is a huge rectangular billboard of

hdu 3016 Man Down (线段树 + dp)

题目大意: 是男人就下一般层...没什么可以多说的吧. 注意只能垂直下落. 思路分析: 后面求最大值的过程很容易想到是一个dp的过程 . 因为每一个plane 都只能从左边 从右边下两种状态. 然后我们所需要处理的问题就是 ,你如何能快速知道往左边下到哪里,往右边下到哪里. 这就是线段树的预处理. 讲线段按照高度排序. 然后按照高度从小到大加入到树中. 然后去寻找左端点 和 右端点最近覆盖的线段的编号. #include <cstdio> #include <iostream> #

HDU 3954 Level up 线段树

---NotOnlySuccess 出的题--- 看了题之后觉得和HDU 4027有点像,给的K很小,只有10,目测只要有人升级的时候直接更新到叶子节点就ok了.不过不同于HDU 4027 的是,那题每一次更新都相当于这题的一次升级操作,这题里面可能会出现一次操作之后没有升级和出现升级两种情况,一时半会没了思路. 无奈去搜题解,发现我只要维护一个区间当中距离升级最近的人所需要的基础升级经验,即不算等级加成的裸的升级经验,如果在一次涨经验之后,出现当前区间当中有人会升级,直接将每一个要升级的人更新

多校训练hdu --Nice boat(线段树,都是泪)

Nice boat Time Limit: 30000/15000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 47 Accepted Submission(s): 10 Problem Description There is an old country and the king fell in love with a devil. The devil always ask

HDU 3308 LCIS(线段树)

Problem Description Given n integers.You have two operations:U A B: replace the Ath number by B. (index counting from 0)Q A B: output the length of the longest consecutive increasing subsequence (LCIS) in [a, b]. Input T in the first line, indicating

HDU 2795 Billboard (线段树单点更新)

题意:h,w,n:有一个h*w尺寸的木板,n张1*wi的海报,贴海报的位置尽量高,尽量往左,问每张海报贴的高度 看到1 <= h,w <= 10^9; 1 <= n <= 200,000,应该就是线段树了. 关键在怎么建树,这里我们对h进行分割,每个高度都有等长的w,我们从上往下贴,如果当前高度 (在同一高度上l==r)的长度可以满足wi则可以贴,否则继续往下寻找. #include <iostream> #include <stdio.h> #includ

HDU—4046 Panda (线段树)

题目:http://acm.hdu.edu.cn/showproblem.php?pid=4046 题意:给出一个字符串,统计这个字符串任意区间中"wbw"出现的次数. 规定两种操作,一是查询任意区间"wbw"出现次数:二是修改某一位置的字符. 分析:比较明显的线段树,单点更新,区间查询. 线段树记录的信息是区间中出现"wbw"字符的个数,线段树的叶子节点[i,i]记录字符串str中 str[i-2][i-1][i]是否是"wbw&qu