【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; } } } }
相关文章推荐
- 【JZOJ5260】【GDOI2018模拟8.12】区间第k小
- 【GDOI2018模拟8.12】区间第k小
- 【GDOI2018模拟8.12】区间第k小
- 【JZOJ5262】【GDOI2018模拟8.12】树(DP,性质题)
- [JZOJ5261]【GDOI2018模拟8.12】求和
- 【JZOJ5262】【GDOI2018模拟8.12】树
- 【JZOJ5229】【GDOI2018模拟7.14】小奇的糖果
- 【JZOJ 5250】【GDOI2018模拟8.11】质数
- 【GDOI2018模拟8.12】求和
- 【JZOJ 5205】【GDOI2018模拟7.6】仰望星空
- JZOJ 5207【GDOI2018模拟7.7】暴力大神hxx
- 【jzoj5223】【GDOI2018模拟7.12】【B】【矩阵乘法】
- [JZOJ5250]【GDOI2018模拟8.11】质数
- 【JZOJ5270】【GDOI2018模拟8.14】神奇的矩阵
- 【JZOJ 5204】【GDOI2018模拟7.6】吃干饭
- 【JZOJ 5229】【GDOI2018模拟7.14】小奇的糖果
- 【JZOJ 5260】 区间第k小
- JZOJ5242【GDOI2018模拟8.8】矩阵
- 【jzoj5251】【GDOI2018模拟8.11】【决战】【状态压缩动态规划】
- 【JZOJ5222】【GDOI2018模拟7.12】A