[JSOI2008]最大数

题目传送门

这道题需要解决的是区间求值和单点修改,可以用线段树求解,首先构造一颗[1,m]的“空树”(序列至多有m个数),即每个节点维护的信息均为0,新建一个变量sum表示序列中实际数的个数,每次修改第sum个节点,最后n个数就是[sum-n+1,sum],简单维护即可。

下面给出参考代码:

 1 #include<iostream>
 2 #include<cstring>
 3 using namespace std;
 4 struct node
 5 {
 6     int l,r,maxn;
 7 }tree[800008];
 8 int m,d,n,t,sum;
 9 char q;
10 void build(int k,int l,int r)
11 {
12     tree[k].maxn=-21374404;tree[k].l=l;tree[k].r=r;
13     if(l==r)return;
14     int mid=(l+r)/2;
15     build(k*2,l,mid);
16     build(k*2+1,mid+1,r);
17 }
18 void add(int k,int l,int r)
19 {
20     int ll=tree[k].l,rr=tree[k].r;
21     if(ll==rr)
22     {
23         tree[k].maxn=n;
24         return;
25     }
26     int mid=(ll+rr)/2;
27     if(sum<=mid)add(k*2,l,r);
28     else add(k*2+1,l,r);
29     tree[k].maxn=max(tree[k*2].maxn,tree[k*2+1].maxn)%d;
30 }
31 int query(int k,int l,int r)
32 {
33     int ll=tree[k].l,rr=tree[k].r;
34     if(ll>=l&&rr<=r)
35     {
36         return tree[k].maxn;
37     }
38     int mid=(ll+rr)/2;
39     int lc=-123456,rc=-123456;
40     if(sum-n+1<=mid)lc=query(k*2,l,r);
41     if(sum>mid)rc=query(k*2+1,l,r);
42     return max(lc,rc)%d;
43 }
44 void check(int l,int r,int k)
45 {
46     if(l==r)
47     {
48         cout<<tree[k].maxn<<" ";
49         return;    
50     }
51     int mid=(l+r)/2;
52     check(l,mid,k*2);
53     check(mid+1,r,k*2+1);
54     return;
55 }
56 int main()
57 {
58     cin>>m>>d;
59     build(1,1,m);
60     for(int i=1;i<=m;i++)
61     {
62         cin>>q>>n;
63         if(q=='A')
64         {
65             n+=t;
66             n%=d;
67             sum++;
68             add(1,1,sum);
69         }
70         else
71         {
72             t=query(1,sum-n+1,sum)%d;
73             cout<<t<<endl;
74         }
75     }
76     return 0;
77 }
View Code
原文地址:https://www.cnblogs.com/szmssf/p/11079547.html