题目大意:维护一种数据结构,支持两个功能:查询区间最大,插入到数列的最后。
思路:一眼就看到是线段树了,没什么好说的。只有一点要注意,插入的时候线段树的范围不要跟着序列中的总数走,那样建完节点之后无法更新父亲节点的信息。
CODE:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 200010 #define MO d #define LEFT (pos << 1) #define RIGHT (pos << 1|1) using namespace std; int cnt,asks,d; int tree[MAX << 2]; int last; char c[10]; void Modify(int l,int r,int aim,int pos,int c); int Ask(int l,int r,int x,int y,int pos); int main() { cin >> asks >> d; for(int x,i = 1;i <= asks; ++i) { scanf("%s",c); switch(c[0]) { case 'Q': scanf("%d",&x); last = Ask(1,MAX - 1,cnt - x + 1,cnt,1); printf("%d\n",last); break; case 'A': cnt++; scanf("%d",&x); Modify(1,MAX - 1,cnt,1,(x + last) % MO); break; } } return 0; } void Modify(int l,int r,int aim,int pos,int c) { if(l == r) { tree[pos] = c; return ; } int mid = (l + r) >> 1; if(aim <= mid) Modify(l,mid,aim,LEFT,c); else Modify(mid + 1,r,aim,RIGHT,c); tree[pos] = max(tree[LEFT],tree[RIGHT]); } int Ask(int l,int r,int x,int y,int pos) { if(l == x && r == y) return tree[pos]; int mid = (l + r) >> 1; if(y <= mid) return Ask(l,mid,x,y,LEFT); if(x > mid) return Ask(mid + 1,r,x,y,RIGHT); int left = Ask(l,mid,x,mid,LEFT); int right = Ask(mid + 1,r,mid + 1,y,RIGHT); return max(left,right); }