HDU 1754 I Hate It (线段树初步point的修改)HDU 3074 Multiply game (增加同余定理)

数据量比较大。。。这是一个比较简单的线段树,每个线段的最大值作为其属性。

左右代表其长度,不断dfs下去。


HDU 1754

I Hate It

Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)


Problem Description
很多学校流行一种比较的习惯。老师们很喜欢询问,从某某到某某当中,分数最高的是多少。
这让很多学生很反感。

不管你喜不喜欢,现在需要你做的是,就是按照老师的要求,写一个程序,模拟老师的询问。当然,老师有时候需要更新某位同学的成绩。
 

Input
本题目包含多组测试,请处理到文件结束。
在每个测试的第一行,有两个正整数 N 和 M ( 0<N<=200000,0<M<5000 ),分别代表学生的数目和操作的数目。
学生ID编号分别从1编到N。
第二行包含N个整数,代表这N个学生的初始成绩,其中第i个数代表ID为i的学生的成绩。
接下来有M行。每一行有一个字符 C (只取'Q'或'U') ,和两个正整数A,B。
当C为'Q'的时候,表示这是一条询问操作,它询问ID从A到B(包括A,B)的学生当中,成绩最高的是多少。
当C为'U'的时候,表示这是一条更新操作,要求把ID为A的学生的成绩更改为B。
 

Output
对于每一次询问操作,在一行里面输出最高成绩。
 

Sample Input
  
  
5 6 1 2 3 4 5 Q 1 5 U 3 6 Q 3 4 Q 4 5 U 2 9 Q 1 5
 

Sample Output
  
  
5 6 5 9
Hint
Huge input,the C function scanf() will work better than cin

//#pragma comment(linker, "/STACK:102400000,102400000")
#include "iostream"
#include "cstring"
#include "algorithm"
#include "cmath"
#include "cstdio"
#include "sstream"
#include "queue"
#include "vector"
#include "string"
#include "stack"
#include "cstdlib"
#include "deque"
#include "fstream"
#include "map"
using namespace std;
typedef long long LL;
const int INF = 0x1fffffff;
const int MAXN = 1000000+100;
#define eps 1e-14
const int mod = 95041567;

int n,m;
int mark[200000+100];

struct node
{
    int left,right;
    int maxc;
}btree[2000000+100];

int build(int root,int left,int right)//建立线段树,maxc
{
    btree[root].left=left;
    btree[root].right=right;
    int mid;
    if (left==right)
        return btree[root].maxc=mark[left];
    else
        mid=(left+right)/2;
    return btree[root].maxc=max(build(2*root,left,mid),build(2*root+1,mid+1,right));
}

int findmaxc(int root,int left,int right)
{
    if (left>btree[root].right||btree[root].left>right)//超出范围无大小
        return -1;
    if (btree[root].left>=left&&btree[root].right<=right)//在范围内返回当前节点maxc
        return btree[root].maxc;
    return max(findmaxc(2*root,left,right),findmaxc(2*root+1,left,right));//dfs其他节点
}

int update(int root,int pos,int value)
{
    if (pos<btree[root].left||pos>btree[root].right)//超范围保持原maxc
        return btree[root].maxc;
    if (pos==btree[root].left&&pos==btree[root].right)//找到node更改属性
        return btree[root].maxc=value;
    return btree[root].maxc=max(update(2*root,pos,value),update(2*root+1,pos,value));//更新maxc

}

int main()
{
    //freopen("in","r",stdin);
    //freopen("out","w",stdout);
    while (cin>>n>>m)
    {
        memset(btree,0,sizeof btree);
        for (int i=1;i<=n;i++) cin>>mark[i];
        build(1,1,n);
        for (int i=0;i<m;i++)
        {
            char c;
            int a,b;
            cin>>c>>a>>b;
            if (c=='Q') cout<<findmaxc(1,a,b)<<endl;
            else
            {
                mark[a]=b;
                update(1,a,b);
            }
        }

    }
    return 0;
}

题目 

Multiply game

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)


Problem Description
Tired of playing computer games, alpc23 is planning to play a game on numbers. Because plus and subtraction is too easy for this gay, he wants to do some multiplication in a number sequence. After playing it a few times, he has found it is also too boring. So he plan to do a more challenge job: he wants to change several numbers in this sequence and also work out the multiplication of all the number in a subsequence of the whole sequence.
  To be a friend of this gay, you have been invented by him to play this interesting game with him. Of course, you need to work out the answers faster than him to get a free lunch, He he…

 

Input
The first line is the number of case T (T<=10).
  For each test case, the first line is the length of sequence n (n<=50000), the second line has n numbers, they are the initial n numbers of the sequence a1,a2, …,an,
Then the third line is the number of operation q (q<=50000), from the fourth line to the q+3 line are the description of the q operations. They are the one of the two forms:
0 k1 k2; you need to work out the multiplication of the subsequence from k1 to k2, inclusive. (1<=k1<=k2<=n)
1 k p; the kth number of the sequence has been change to p. (1<=k<=n)
You can assume that all the numbers before and after the replacement are no larger than 1 million.
 

Output
For each of the first operation, you need to output the answer of multiplication in each line, because the answer can be very large, so can only output the answer after mod 1000000007.
 

Sample Input
  
  
1 6 1 2 4 5 6 3 3 0 2 5 1 3 7 0 2 5
 

Sample Output
  
  
240 420
#pragma comment(linker, "/STACK:102400000,102400000")
#include "iostream"
#include "cstring"
#include "algorithm"
#include "cmath"
#include "cstdio"
#include "sstream"
#include "queue"
#include "vector"
#include "string"
#include "stack"
#include "cstdlib"
#include "deque"
#include "fstream"
#include "map"
using namespace std;
typedef long long LL;
const int INF = 0x1fffffff;
const int MAXN = 1000000+100;
#define eps 1e-14
const int mod = 1000000007;

int n,q;
int val[50000+100];

struct node
{
    int left,right;
    LL multi;
}btree[150000+100];

LL build(int root,int left,int right)
{
    btree[root].left=left;
    btree[root].right=right;
    int mid;
    if (left==right)
        return btree[root].multi=val[left];
    else mid=(left+right)/2;
    return btree[root].multi=build(2*root,left,mid)*build(2*root+1,mid+1,right)%mod;

}

LL findmulti(int root,int left,int right)
{
    if (btree[root].left>right||btree[root].right<left)
        return 1;
    if (btree[root].left>=left&&btree[root].right<=right)
        return btree[root].multi;
    return findmulti(2*root,left,right)*findmulti(2*root+1,left,right)%mod;//同余定理
}

LL update(int root,int pos,int val)
{
    if (btree[root].left>pos||btree[root].right<pos)
        return btree[root].multi;
    if (btree[root].left==pos&&btree[root].right==pos)
        return btree[root].multi=val;
    return btree[root].multi=update(2*root,pos,val)*update(2*root+1,pos,val)%mod;
}

int main()
{
    //freopen("in","r",stdin);
    //freopen("out","w",stdout);
    int t;
    scanf("%d",&t);
    while (t--)
    {
        memset(btree,0,sizeof btree);
        scanf("%d",&n);
        for (int i=1;i<=n;i++) scanf("%d",&val[i]);
        build(1,1,n);
        scanf("%d",&q);
        for (int i=0;i<q;i++)
        {
            bool a;
            int b,c;
            scanf("%d%d%d",&a,&b,&c);
            if (!a) printf("%I64d\n",findmulti(1,b,c)%mod);
            else if (a)
            {
                val[b]=c;
                update(1,b,c);
            }
        }


    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值