您的位置:首页 > 其它

区间相关值问题

2015-10-22 17:18 323 查看
这是一篇奇怪向的总结==

区间max,区间和。。。线段树直接搞

区间中位数,树套树或许可以但或许不优。。。

区间mex(无修改):首先[1,x],1≤x≤n单调扫一遍即可,

同时处理出该位置上的数下一次出现位置,记为next[i]

然后我们对询问排序,考虑i上数对后面数的影响,即为[i,next[i]−1]上mex>=num[i]变为num[i],套上线段树区间修改即可。(ps:带修改或许可以用带修莫队)code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#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 (l<a.l)||(l==a.l&&r<a.r);}
}qst[200001];
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 (now<qst[i].l)
{
insert(1,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<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
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]<ans))
{
maxn=num[a[i]];
ans=a[i];
}
num[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]<ans))
{
maxn=f[a[j]][i]-f[a[j]][i-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]<ans))
{
maxn=f[a[k]][j]-f[a[k]][i-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);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: