您的位置:首页 > 其它

【JZOJ5260】【GDOI2018模拟8.12】区间第k小(分块)

2017-08-21 07:49 417 查看

Description



Solution

首先这题离线的话是可以莫队套分块的,但是要求强制在线。那么我们只能考虑把莫队换成分块。

首先处理一个关于值域的块,然后求一个数组f[i,j,k]表示从下标第i块到第j块中满足在值域块是第k块,且这些数字出现次数小于等于w的有多少个,这个枚举两个端点,然后扫过去,用桶记录一下就好了。

然后再处理一个数组g[i,j]表示前i块中值为j的有多少个。

那么现在我们就可以考虑先把答案用f确定是哪一个块,然后再用g确定是那一个数字。

对于询问[l,r]先把两边下标多余的部分(就是不是整段都在块中)与中间的合并,具体就是统计其中数字出现的次数,然后与中间部分出现的次数相加,如果大于w,那么求答案的时候就不能考虑(就是把f减掉),否则就把f加上两边出现的次数,最后做完再加(减)回

来。然后先找到确定的块,然后枚举块中的数字确定是哪一个就好了。

复杂度O(nn√)

Code

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
const int maxn=1e5+7;
int i,j,k,l,t,n,m,ans,type,w,q,r,o,l1,r1,yi,er,x;
int f[350][350][350],g[350][maxn],c[maxn],d[maxn];
int a[maxn],e1,e2,shu[maxn],b[maxn],w1,w2;
bool bz[maxn];
int main(){
freopen("kth.in","r",stdin);
freopen("kth.out","w",stdout);
scanf("%d%d%d%d",&n,&w,&q,&type);e1=sqrt(n);
fo(i,1,n)scanf("%d",&a[i]),shu[i]=(i-1)/e1+1;w1=shu
;
e2=sqrt(maxn-7);fo(i,0,maxn-7)b[i]=i/e2+1;w2=b[maxn-7];
fo(i,1,n)g[shu[i]][a[i]]++;
fo(j,0,maxn-7)fo(i,1,w1)g[i][j]+=g[i-1][j];
fo(i,1,w1){
fo(j,i,w1){
fo(l,(j-1)*e1+1,j*e1){
if(l>n)break;
if(d[a[l]]<0)continue;
d[a[l]]++;
if(d[a[l]]>w)f[i][j][b[a[l]]]-=d[a[l]]-1,d[a[l]]=-1;
else f[i][j][b[a[l]]]++;
}
}
memset(d,0,sizeof(d));
}
fo(k,1,w2)fo(i,1,w1)fo(j,i+1,w1)f[i][j][k]+=f[i][j-1][k];
while(q--){
scanf("%d%d%d",&l,&r,&k);l^=(ans*type),r^=(ans*type),k^=(ans*type);
l1=shu[l]*e1+1;r1=(shu[r]-1)*e1;yi=shu[l1],er=shu[r1];o=0;t=0;c[0]=0;
if(l1<r1){
fo(i,l,l1-1)d[a[i]]++,c[++c[0]]=a[i];fo(i,r1+1,r)d[a[i]]++,c[++c[0]]=a[i];
fo(i,1,c[0])if(!bz[c[i]]){
x=c[i];bz[x]=1;
if(g[er][x]-g[yi-1][x]<=w&&g[er][x]-g[yi-1][x]+d[x]>w)f[yi][er][b[x]]-=g[er][x]-g[yi-1][x];
else if(g[er][x]-g[yi-1][x]+d[x]<=w)f[yi][er][b[x]]+=d[x];
}
}
else{
yi=er=w2+2;
fo(i,l,r)d[a[i]]++,c[++c[0]]=a[i];
fo(i,l,r)if(!bz[a[i]]){
bz[a[i]]=1;
if(d[a[i]]<=w)f[yi][er][b[a[i]]]+=d[a[i]];
}
}
fo(i,1,w2){
o+=f[yi][er][i];
if(o>=k){t=i;o-=f[yi][er][i];break;}
}
if(t){
fo(i,(t-1)*e2,t*e2-1){
if(i>maxn-7)break;
if(i==154){
ans=ans;
}
if(g[er][i]-g[yi-1][i]+d[i]){
ans=ans;
}
if(g[er][i]-g[yi-1][i]+d[i]>w)continue;
o+=g[er][i]-g[yi-1][i]+d[i];
if(o>=k){
ans=i;
break;
}
}
}
if(o<k)ans=n;
printf("%d\n",ans);
fo(i,1,c[0]){
if(bz[c[i]]){
x=c[i];bz[x]=0;
if(g[er][x]-g[yi-1][x]<=w&&g[er][x]-g[yi-1][x]+d[x]>w)f[yi][er][b[x]]+=g[er][x]-g[yi-1][x];
else if(g[er][x]-g[yi-1][x]+d[x]<=w)f[yi][er][b[x]]-=d[x];
d[x]=0;
}
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: