这是一篇奇怪向的总结==
区间max,区间和。。。线段树直接搞
区间中位数,树套树或许可以但或许不优。。。
区间mex(无修改):首先 [1,x],1≤x≤n 单调扫一遍即可,
同时处理出该位置上的数下一次出现位置,记为 next[i]
然后我们对询问排序,考虑 i 上数对后面数的影响,即为 [i,next[i]−1] 上 mex>=num[i] 变为 num[i] ,套上线段树区间修改即可。(ps:带修改或许可以用带修莫队)code:
#include
#include
#include
#include
#define inf 0x7fffffff
#define mid (l+r)/2
#define lch i<<1,l,mid
#define rch i<<1|1,mid+1,r
using namespace std;
int n,m,ans;
struct hp{
int mex,delta;
}seg[800001];
int ansi[200001];
int next[200001],last[200001];
struct hq{
int l,r,num;
bool operator < (const hq &a) const
{return (l200001];
bool mark[200001];
int st[200001],xl[200001];
void build(int i,int l,int r)
{
seg[i].delta=inf;
if (l==r)
{
seg[i].mex=st[l];
return;
}
build(lch); build(rch);
}
void pushdown(int i)
{
int a=seg[i].delta;
seg[i<<1].delta=min(seg[i<<1].delta,a);
seg[i<<1|1].delta=min(seg[i<<1|1].delta,a);
seg[i<<1].mex=min(seg[i<<1].mex,a);
seg[i<<1|1].mex=min(seg[i<<1|1].mex,a);
seg[i].delta=inf;
}
void insert(int i,int l,int r,int x,int y,int a)
{
if (x<=l&&y>=r)
{
seg[i].mex=min(seg[i].mex,a);
seg[i].delta=min(seg[i].delta,a);
return;
}
if (seg[i].delta!=inf)
pushdown(i);
if (x<=mid) insert(lch,x,y,a);
if (y>mid) insert(rch,x,y,a);
}
void query(int i,int l,int r,int x)
{
if (l==x&&l==r)
{
ans=seg[i].mex;
return;
}
if (seg[i].delta!=inf)
pushdown(i);
if (x<=mid) query(lch,x); if (x>mid) query(rch,x);
}
int main()
{
int i,k=0,now;
scanf("%d%d",&n,&m);
for (i=1;i<=n;++i)
scanf("%d",&xl[i]);
for (i=1;i<=n;++i)
{
mark[xl[i]]=1;
if (xl[i]==k)
while (mark[k])
k++;
st[i]=k;
}
build(1,1,n);
for (i=n;i>=1;--i)
{
next[i]=last[xl[i]];
if (last[xl[i]]==0) next[i]=n+1;
last[xl[i]]=i;
}
for (i=1;i<=m;++i)
{
scanf("%d%d",&qst[i].l,&qst[i].r);
qst[i].num=i;
}
sort(qst+1,qst+m+1);
now=1;
for (i=1;i<=m;++i)
{
while (now1,1,n,now,next[now]-1,xl[now]);
now++;
}
query(1,1,n,qst[i].r);
ansi[qst[i].num]=ans;
}
for (i=1;i<=m;++i)
printf("%d\n",ansi[i]);
}
区间众数(无修改),分块做法,比较简单,参考一下代码吧
g[i][j] 表示从第 i 个块开始到第 j 个结束的众数
f[x][i] 表示 x 在前 i 个块内的出现次数
code:
#include
#include
#include
#include
#include
using namespace std;
int f[40001][201],g[201][201];
int fa[40001];
int a[40001],b[40001],cnt[40001];
int block[201],num[40001];
int n,m,t,lastans;
void work(int l,int r)
{
int i,st,en,ans,maxn;
st=lower_bound(block+1,block+t+1,l)-block;
en=lower_bound(block+1,block+t+1,r)-block;
if (en-st<=1)
{
for (i=l;i<=r;++i)
num[a[i]]++;
ans=0; maxn=0;
for (i=l;i<=r;++i)
{
if ((num[a[i]]>maxn)||(num[a[i]]==maxn&&a[i]0;
}
}
else
{
ans=g[st+1][en-1]; maxn=f[ans][en-1]-f[ans][st];
for (i=l;i<=block[st];++i)
num[a[i]]++;
for (i=block[en-1]+1;i<=r;++i)
num[a[i]]++;
for (i=l;i<=block[st];++i)
{
if ((num[a[i]]+f[a[i]][en-1]-f[a[i]][st]>maxn)||(num[a[i]]+f[a[i]][en-1]-f[a[i]][st]==maxn&&ans>a[i]))
{
maxn=f[a[i]][en-1]-f[a[i]][st]+num[a[i]];
ans=a[i];
}
num[a[i]]=0;
}
for (i=block[en-1]+1;i<=r;++i)
{
if ((num[a[i]]+f[a[i]][en-1]-f[a[i]][st]>maxn)||(num[a[i]]+f[a[i]][en-1]-f[a[i]][st]==maxn&&ans>a[i]))
{
maxn=f[a[i]][en-1]-f[a[i]][st]+num[a[i]];
ans=a[i];
}
num[a[i]]=0;
}
}
printf("%d\n",fa[ans]);
lastans=fa[ans];
}
int main()
{
int i,per,k,j,size,l,r;
int ans,maxn;
scanf("%d%d",&n,&m); per=sqrt(n);
for (i=1;i<=n;++i)
{
scanf("%d",&a[i]);
b[i]=a[i];
}
sort(b+1,b+n+1);
size=unique(b+1,b+n+1)-b-1;
for (i=1;i<=n;++i)
{
t=upper_bound(b+1,b+size+1,a[i])-b-1;
fa[t]=a[i];
a[i]=t;
}
t=0;
for (i=per;i<=n;i+=per)
block[++t]=i;
if (block[t]!=n) block[++t]=n;
j=1;
for (i=1;i<=n;++i)
{
cnt[a[i]]++;
if (i==block[j])
{
for (k=1;k<=n;++k)
f[k][j]=cnt[k];
j++;
}
}
for (i=1;i<=t;++i)
{
maxn=0; ans=0;
for (j=block[i-1]+1;j<=block[i];++j)
if ((f[a[j]][i]-f[a[j]][i-1]>maxn)||(f[a[j]][i]-f[a[j]][i-1]==maxn&&a[j]1];
ans=a[j];
}
g[i][i]=ans;
}
for (i=1;i<=t;++i)
for (j=i+1;j<=t;++j)
{
ans=g[i][j-1];
maxn=f[ans][j]-f[ans][i-1];
for (k=block[j-1]+1;k<=block[j];++k)
if ((f[a[k]][j]-f[a[k]][i-1]>maxn)||(f[a[k]][j]-f[a[k]][i-1]==maxn&&a[k]1];
ans=a[k];
}
g[i][j]=ans;
}
for (i=1;i<=m;++i)
{
scanf("%d%d",&l,&r);
l=(l+lastans-1)%n+1;
r=(r+lastans-1)%n+1;
if (l>r) swap(l,r);
work(l,r);
}
}