bzoj 1012 最大数(线段树|单调队列|单调栈)

1012: [JSOI2008]最大数maxnumber

Time Limit: 3 Sec   Memory Limit: 162 MB
Submit: 5572   Solved: 2424
[ Submit][ Status][ Discuss]

Description

现在请求你维护一个数列,要求提供以下两种操作: 1、 查询操作。语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值。限制:L不超过当前数列的长度。 2、 插入操作。语法:A n 功能:将n加上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取模,将所得答案插入到数列的末尾。限制:n是非负整数并且在长整范围内。注意:初始时数列是空的,没有一个数。

Input

第一行两个整数,M和D,其中M表示操作的个数(M <= 200,000),D如上文中所述,满足(0

Output

对于每一个查询操作,你应该按照顺序依次输出结果,每个结果占一行。

Sample Input

5 100
A 96
Q 1
A 97
Q 1
Q 2

Sample Output

96
93
96

思路:
查询区间内的最大值,并且M又有200000这么大,所以要用线段树。开始没仔细考虑数据大小,我用单链表写。。自然超时了

代码:
//这是单链表写的,超时
#include
#include
using namespace std;
#define LIST_NUM 200000
typedef int ElemType;

typedef struct LNode
{
    ElemType data;
    struct LNode *next;
}LNode,*LinkList;

void InitList(LinkList &L)
{
    L=new LNode;
    L->next=NULL;
}

void CreatList(LinkList L,ElemType e)
{
    LNode *p;
    p=new LNode;
    if(L->next==NULL){
        L->next=p;
        p->next=NULL;
    }
    else{
        p->next=L->next;
        L->next=p;
    }
    p->data=e;
}

void ShowList(LinkList L)
{
    LNode *s=L->next;
    while(s)
    {
        cout<data<<" ";
        s=s->next;
    }
    cout<>M>>D;
    int num;
    int en;
    int flag=0;
    for(int i=1;i<=M;i++)
    {
        cin>>ask>>num;
        if(ask=='A')
        {
            if(flag==0)
                en=0;
            int t=num+en;
            t=t%D;
            CreatList(L,t);
        }
        else if(ask=='Q')
        {
            LNode *s=L->next;
            int maxn=0;
            while(num--)
            {
                if(s->data>maxn)
                    maxn=s->data;
                s=s->next;
            }
            cout<


//线段树写的,AC
#include
#include
#include
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define maxn 200005
int n,mod,last;
int big[maxn<<2];

void Pushup(int rt)
{
    big[rt] = max(big[rt<<1],big[rt<<1|1]);
}

void updata(int L,int num,int l,int r,int rt)
{
    if(l==r)
    {
        big[rt] = num;
        return;
    }
    int m = (l+r)>>1;
    if(L<=m)
        updata(L,num,lson);
    else
        updata(L,num,rson);
    Pushup(rt);
}

int query(int L,int R,int l,int r,int rt)
{
    if(L<=l && R>=r)
        return big[rt];
    int m = (l+r)>>1;
    int ret = 0;
    if(L<=m)
        ret = max(ret,query(L,R,lson));
    if(R > m)
        ret = max(ret,query(L,R,rson));
    return ret;
}

int main()
{
    char op[5];
    cin>>n>>mod;
    last = 0;
    int k,len=0;
    for(int i=0;i

下面两个是HZWER博客上看到的。。智商压制。。

//单调栈
#include
#include
#include
#include
int n,d,t;
int top,len,a[200001],num[200001];
int main()
{
    int x;char ch[1];
    scanf("%d%d",&n,&d);
    while(n--)
    {
              scanf("%s%d",ch,&x);
              if(ch[0]=='A')
              {
                      x=(x+t)%d;
                      num[++len]=x;
                      while(top&&num[a[top]]<=x)top--;
                      a[++top]=len;      
                      }
              else{
                  int y=lower_bound(a+1,a+top+1,len-x+1)-a;
                  t=num[a[y]];
                  printf("%d\n",t=num[a[y]]);
              }
          }
    return 0;
}

//单调队列:
#include
int m,d,a[200001],t,max[200001],l=0,p;
char q[1];
int main()
{
	scanf("%d%d", &m, &d);
	while (m--)
	{
		scanf("%s%d",q,&p);
		if(q[0]=='A')
		{
			a[++t]=(l+p)%d;
			for(int i=t;i;i--)
				if(max[i]





你可能感兴趣的:(单调队列,线段树)