分析:首先简单高效的做法为单调栈,代码短,效率高。不过本渣由于不会就写的线段树,得了80分。我想的线段树的写法是先存入各操作,建树后离线操作。每次询问后修改相关节点(具体见代码),最后两点未过,不知何因。
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
using namespace std;
int m,D,sum,t,x,maxn,sum1,sum2,ss,tt,num1[200001],num2[200001][2],sq[800001];
char c;
void build_tree(int s,int t,int now)
{
int mid;
if (s==t)
{
sq[now]=num1[s];
return;
}
mid=(s+t)/2;
build_tree(s,mid,now*2);
build_tree(mid+1,t,now*2+1);
sq[now]=max(sq[now*2],sq[now*2+1]);
}
int find_tree(int s,int t,int now)
{
int mid,ans;
if (s>=ss&&t<=tt) return sq[now];
mid=(s+t)/2;
if (ss<=mid) ans=find_tree(s,mid,now*2); else ans=-1;
if (tt>mid) ans=max(ans,find_tree(mid+1,t,now*2+1));
return ans;
}
void fix_tree(int s,int t,int now)
{
int mid;
if (s==ss&&s==t)
{
sq[now]=tt;
return;
}
mid=(s+t)/2;
if (ss<=mid)
{
fix_tree(s,mid,now*2);
sq[now]=max(sq[now*2],sq[now*2+1]);
}
if (ss>mid)
{
fix_tree(mid+1,t,now*2+1);
sq[now]=max(sq[now*2],sq[now*2+1]);
}
}
int main()
{
scanf("%d%d",&m,&D);
getchar();
t=0;
sum=0;
for (int i=1;i<=m;i++)
{
c=getchar();
scanf("%d",&x);
if (c==‘A‘)
{
sum1++;
num1[sum1]=x;
}
if (c==‘Q‘)
{
sum2++;
num2[sum2][1]=sum1-x+1;
num2[sum2][2]=sum1;
}
getchar();
}
build_tree(1,sum1,1);
for (int i=1;i<=sum2;i++)
{
ss=num2[i][1];
tt=num2[i][2];
t=find_tree(1,sum1,1);
printf("%d\n",t);
if (num2[i][2]==sum1) continue;
for (int j=num2[i][2]+1;j<=num2[i+1][2];j++)
{
ss=j;
tt=(num1[j]%D+t%D)%D;
fix_tree(1,sum1,1);
}
}
return 0;
}