1198 最大数
这个题我之前用线段树做过,这次使用单调栈来解决,还可以使用ST、树状数组来解决
插入操作相当于入栈的操作,时间复杂度在于O(1),这个很好操作,问题就在于查询操作
其实单调栈经常运用在二分答案题,这个题就是这样的,所以,单调数据结构就经常和二分在一起,并且还是对顶堆
先开两个栈,第一个存储队列中的位置,第二个存储数字的大小
当有新的元素需要入队的时候 ,我们可以吧排在这个元素前面的比他小的数全部忽略,然后更新两个栈即可
接下来我们就可以二分栈的下表,知道二分到一个位置使得表示的位置在所求的位置里面,那么就求的答案了
所以,本质上还是查找,只不过优化了二分
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int SIZE=2e6+5;
ll m,mod;
char opt;
ll w;
ll stack[2][SIZE],top,cnt;
ll t;
inline ll read()
{
char ch=getchar();
ll s=0,f=1;
while(ch<'0'||ch>'9')
{
ch=getchar();
if(ch=='-') f=-1;
}
while(ch>='0'&&ch<='9')
s*=10,s+=ch-48,ch=getchar();
return s*f;
}
void add(int x)
{
cnt++;
while(x>stack[1][top]&&top>0) top--;//忽略无用信息
stack[0][++top]=cnt;//记录下标
stack[1][top]=x;//记录元素
}
void query(int x,int l,int r)
{
while(l<r)
{
int mid=(l+r)/2;//二分查找
if(stack[0][mid]<x) l=mid+1;
else r=mid;
}
t=stack[1][r];
cout<<t<<endl;
}
int main()
{
m=read(),mod=read();
while(m--)
{
while(opt!='A'&&opt!='Q') opt=getchar();
opt=getchar();
w=read();
if(opt=='A')
add((t+w)%mod);//添加元素
else
query(cnt-w+1,1,top);//末尾x个数在栈中查找
}
return 0;
}
线段树
其实感觉这样比较基础的线段树都是在模板的修改查询上东东手脚,有的时候将求和改成复制,有的时候改变懒标记
所以,我们需要将最基础的东西进行改变
#include <iostream>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
using namespace std;
#define root 1, m, 1
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
int m, d, q[12345678], t;
void build(int l, int r, int rt)
{
q[rt] = -214783647;
if (l == r)
return ;
int mid = (l + r) >> 1;
build(lson);
build(rson);
}
int input_int;
char input_char;
void plusa(int l, int r, int rt, int p, int v)
{
if (l == r)
{
q[rt] = v;
return ;
}
int mid = (l + r) >> 1;
if (p <= mid) plusa(lson, p, v);
else plusa(rson, p, v);
q[rt] = max(q[rt << 1], q[rt << 1 | 1]);
}
int sth;
int ask(int l, int r, int rt, int nowl, int nowr)
{
if (nowl <= l && r <= nowr) return q[rt];
int mid = (l + r) >> 1;
int minn = -2147483647;
if (nowl <= mid) minn = ask(lson, nowl, nowr);
if (nowr > mid) minn = max(minn, ask(rson, nowl, nowr));
return minn;
}
int main()
{
scanf("%d%d", &m, &d);
build(root);
for (int i = 1; i <= m; ++i)
{
cin >> input_char >> input_int;
if (input_char == 'A')
{
sth ++;
plusa(root, sth, (input_int + t) % d);
}
else
{
t = ask(root, sth - input_int + 1, sth);
cout << t << endl;
}
}
return 0;
}