[JSOI2008]最大数 线段树解法

题目描述

现在请求你维护一个数列,要求提供以下两种操作:

1、 查询操作。

语法:Q L

功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值。

限制:L不超过当前数列的长度。

2、 插入操作。

语法:A n

功能:将n加上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取模,将所得答案插入到数列的末尾。

限制:n是整数(可能为负数)并且在长整范围内。

注意:初始时数列是空的,没有一个数。

                                  --by luogu

https://daniu.luogu.org/problem/show?pid=1198



先把序列的空位建好线段树,初始序列是空的,就先建为极小值(注意她是的),对每个A操作,就是在相应位置单点修改,对每个Q操作,就是查询相应的位置的区间最值

位置是什么呢?

发现只要记下当前序列的结尾就迎刃而解啦;

代码如下:

 1 #include<cstdio>
 2 using namespace std;
 3 long long D,n,t;
 4 int tree[1000000];
 5 int m,len;
 6 void build(int ,int ,int );
 7 void change(int ,int, int ,int );
 8 int MAX(int ,int ,int ,int ,int );
 9 int main()
10 {
11     int i,j,k,l;
12     char c;
13     scanf("%d%d",&m,&D);
14     build(1,m,1);
15     for(i=1;i<=m;i++){
16         c=getchar();
17         while(c!='A'&&c!='Q')
18             c=getchar();
19         if(c=='A'){
20             scanf("%lld",&n);
21             n=(n+t)%D;
22             change(1,m,1,len+1);
23             len++;
24         }
25         if(c=='Q'){
26             scanf("%d",&l);
27             t=MAX(1,m,1,len-l+1,len);
28             printf("%lld
",t);
29         }
30     }
31     return 0;
32 }
33 void build(int l,int r,int nu){
34     if(l==r){
35         tree[nu]=-2147483600;
36         return;
37     }
38     int mid=(l+r)>>1;
39     build(l,mid,nu<<1);build(mid+1,r,nu<<1|1);
40     tree[nu]=-2147483600;
41 }
42 void change(int l,int r,int nu,int x){
43     if(l==r){
44         tree[nu]=n;
45         return ;
46     }
47     int mid=(l+r)>>1;
48     if(x<=mid)
49         change(l,mid,nu<<1,x);
50     else
51         change(mid+1,r,nu<<1|1,x);
52     if(tree[nu<<1]>tree[nu<<1|1])
53         tree[nu]=tree[nu<<1];
54     else
55         tree[nu]=tree[nu<<1|1];
56 }
57 int MAX(int l,int r,int nu,int L,int R){
58     if(L<=l&&r<=R)
59         return tree[nu];
60     int mid=(l+r)>>1;
61     int Lmax=-2147483600,Rmax=-2147483600;
62     if(L<=mid)
63         Lmax=MAX(l,mid,nu<<1,L,R);
64     if(R>=mid+1)
65         Rmax=MAX(mid+1,r,nu<<1|1,L,R);
66     if(Lmax>Rmax)
67         return Lmax;
68     return Rmax;
69 }

话说代码真难看呵;


原文地址:https://www.cnblogs.com/nietzsche-oier/p/6516896.html