「BZOJ1012」[JSOI2008] 最大数(线段树/单调栈)

题目

传送门

题解

写线段树的话太裸了,但是题意非常难搞,认真读题:其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取模,将所得答案插入到数列的末尾。–>重新赋值

从题解上看到一种单调栈的写法觉得非常巧妙
利用了题目的特性:每次都是在最后询问,用单调栈维护,开两个栈一个保存下标,一个保存他的值,在插入的时候把栈中比这个值小的都弹出,查询时二分答案即可

代码

线段树

//并将所得结果对一个固定的常数D取模,将所得答案插入到数列的末尾
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1e6;
const int inf=1e9;

int n,mod,last;
char opt[10];
struct Node{
    int mx;
}tree[maxn<<1|1];

void pushup(int rt)
{
    tree[rt].mx=max(tree[rt<<1].mx,tree[rt<<1|1].mx);
}
void change(int x,int C,int l,int r,int rt)
{
    if (l==r) {tree[rt].mx+=C; return;}
    int mid=(l+r)>>1;
    if (x<=mid) change(x,C,l,mid,rt<<1);
    else change(x,C,mid+1,r,rt<<1|1);
    pushup(rt);
}

int ques(int L,int R,int l,int r,int rt)
{
    if (L<=l && r<=R) return tree[rt].mx;
    int mid=(l+r)>>1; int ans=0;
    if (L<=mid) ans=max(ans,ques(L,R,l,mid,rt<<1));
    if (R>mid) ans=max(ans,ques(L,R,mid+1,r,rt<<1|1));
    return ans;
}

int main()
{
    int sz=0;
    scanf("%d%d",&n,&mod);
    for (int i=1; i<=n; i++)
    {
        scanf("%s",opt); int x; scanf("%d",&x);
        if (opt[0]=='A') change(++sz,(x+last)%mod,1,n,1);
        else
        {
            if (!x) {
   
   printf("0\n"); continue;}
            last=ques(sz-x+1,sz,1,n,1);
            printf("%d\n",last);
        }
    }
    return 0;
}

单调栈

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1e6;
const int inf=1e9;

int n,mod,zhan[maxn][2],top,last,sz;
char opt[10];
void change(int x)
{
    while (x>zhan[top][1]&&top>0) top--;
    zhan[++top][0]=++sz;
    zhan[top][1]=x;
}
int ques(int x,int l,int r)
{
    while (l<r)
    {
        int mid=(l+r)>>1;
        if (x>zhan[mid][0]) l=mid+1;
        else r=mid;
    }
    return zhan[l][1];
}
int main()
{
    scanf("%d%d",&n,&mod);
    for (int i=1; i<=n; i++)
    {
        scanf("%s",opt); int x; scanf("%d",&x);
        if (opt[0]=='A') change((x+last)%mod);
        else
        {
            if (!x) {
   
   printf("0\n"); continue;}
            last=ques(sz-x+1,1,top);
            printf("%d\n",last);
        }
    }
    return 0;
}

总结

猜你喜欢

转载自blog.csdn.net/A_Comme_Amour/article/details/79810160
今日推荐