现在的位置: 首页 > 综合 > 正文

maxnumber

2013年10月24日 ⁄ 综合 ⁄ 共 1730字 ⁄ 字号 评论关闭

1012: [JSOI2008]最大数maxnumber

Time Limit: 3 Sec  Memory Limit:
162 MB
Submit: 2286  Solved: 1041
[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

评测链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1012

解法1:线段树:http://blog.csdn.net/yuyanggo/article/details/8841109

解法2:单调队列+并查集:http://blog.csdn.net/yuyanggo/article/details/8844625

解法3:单调队列+二分查找(即本篇所讲);

用a[i]记录第i号点的值,用一个单调递减序列q[](我是从左到右递减)存储从1到n号点所有大于等于a[n]的节点的编号。

对于一个插入操作,假如是插入x,用二分查找找到从左到右第一个<=x的节点的编号j,将q[j]赋值为x的节点编号,并把j后面的元素都删掉(可以用len记录q数组元素总数,把len赋值为j就可以完成这个操作了)

对于一个查询操作Q L,用二分查找找到从左到右第一个>=n-l+1(n为当前节点总数)的点j,然后输出a[q[j]]即可。

(有疑问的欢迎留言)

代码:

#include<cstdio>
#define maxn (200000+100)
using namespace std;
//q记录单调递减队列  a记录节点值 
// n记录节点总数   len记录单调队列中的元素总数 
int q[maxn],a[maxn],n=0,len=0;

void init()
{
  freopen("maxnumber.in","r",stdin);
  freopen("maxnumber.out","w",stdout);
}
//将a[k]=x插入单调队列 
inline void add(int x,int k)
{
  if(x<a[q[len]]){q[++len]=k;return;}
  int l=1,r=len,m;
  while(l<=r)
    {
      m=(l+r)>>1;
      if(x==a[q[m]]){len=m;return;}
      if(x>a[q[m]])r=m-1;
      else l=m+1;
    }
  //找到从左到右第一个<=x的节点的编号L,将q[L]赋值为k(x的节点编号),并将len赋为L,  
  len=l;q[len]=k;  
}

inline int get(int k)
{
  if(len==1)return a[n];
  int l=1,r=len,m;
  while(l<=r)
    {
      m=(l+r)>>1;
      if(q[m]==k)return a[k];
      if(k>q[m])l=m+1;
      else r=m-1;
    }
  //找到从左往右第一个节点编号>=k的点L,a[q[l]]即为从k到n的最大值  
  return a[q[l]];
}

void work()
{
  int m,d,t=0,i,b,k;
  char s; 
  scanf("%d%d\n",&m,&d);
  for(i=1;i<=m;i++)
    {
      scanf("%c%d\n",&s,&b);
      if(s=='A')
        {
          a[++n]=(b+t)%d;
          add(a[n],n);
        }
      else
        printf("%d\n",t=get(n-b+1));
    }   
}

int main()
{
  init();
  work();
  return 0;
}

抱歉!评论已关闭.