【JZOJ5260】【GDOI2018模拟8.12】区间第k小
来源:互联网 发布:用递归算法计算斐波拉 编辑:程序博客网 时间:2024/06/08 12:25
Description
Data Constraint
Solution
我们先考虑离线做法。显然是莫队+数据结构。但我们发现莫队是插入
那么在线呢?我们沿用离线的分块想法。将序列分为根号个块,设ans[i][j][k]表示序列i块到j块上数值在按数值分块的第k块上的满足出现次数不大于w的数的数量,sum[i][j]表示值i在序列前j块出现的次数。ans[i][j][k]可以通过枚举块i,然后枚举i块及其往后的序列,当一个数x出现次数大于w时,我们在其所属的ans[i][j][k]减去其总共出现的次数并将其赋值为-1,保证往后不会再计算,接下来只用ans[i][j][k]加上ans[i][j-1][k]即可抵消x在ans[i][j][k]的贡献。sum[i][j]维护十分简单就不讲了。
我们考虑如何求答案。对于一个询问[l,r]我们可以知道完全被[l,r]包含的块[i,j]的大致答案ans[i][j],但我们还需考虑不在块内的剩余数。我们统计不在块内的数的数量,如某些数x在块[i~j]内出现次数不大于w,而加上不在块内的数量后大于w,我们将其在ans[i][j][k]中减去它的贡献。反之则加上它的贡献。最后我们枚举答案所在的块k,对答案所在的块内暴力计算答案的值即可。时间复杂度O((N+Q)
Code
#include<iostream>#include<cmath>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=1e5+5,maxn1=320,maxn2=1e5;int ans[maxn1][maxn1][maxn1],sum[maxn][maxn1],a[maxn],r[maxn],bz[maxn],bz1[maxn],b[maxn],rr[maxn];int n,m,i,t,j,k,l,x,y,z,bz2,p,ln,q,ans1,test,ln1,qq,num,num1;void dg(int x,int y){ int z=0; for (j=x;j<=y;j++) if (sum[a[j]][k]-sum[a[j]][t-1]<=m){ p=a[j]/qq+1; if (sum[a[j]][k]-sum[a[j]][t-1]+bz[a[j]]>m)ans[t][k][p]-=sum[a[j]][k]-sum[a[j]][t-1]; else ans[t][k][p]+=bz[a[j]]; bz[a[j]]=0; }}void dg1(int x,int y){ for (j=x;j<=y;j++) if (sum[a[j]][k]-sum[a[j]][t-1]<=m){ p=a[j]/qq+1; if (sum[a[j]][k]-sum[a[j]][t-1]+bz1[a[j]]>m)ans[t][k][p]+=sum[a[j]][k]-sum[a[j]][t-1]; else ans[t][k][p]-=bz1[a[j]]; bz1[a[j]]=0; }}int main(){ freopen("kth.in","r",stdin);freopen("kth.out","w",stdout); scanf("%d%d%d%d",&n,&m,&test,&bz2); ln=sqrt(n);q=ln;ln1=sqrt(maxn2);qq=ln1; for (i=1;i<=n;i++)scanf("%d",&a[i]); for (i=1;i<=ln;i++) r[i]=i*ln; for (i=1;i<=ln1;i++) rr[i]=i*ln1-1; r[++ln]=n;rr[++ln1]=maxn2;rr[0]=-1; for (i=1;i<=ln;i++){ for (j=0;j<=maxn2;j++) sum[j][i]=sum[j][i-1]; for (j=r[i-1]+1;j<=r[i];j++) sum[a[j]][i]++; } for (i=1;i<=ln;i++){ k=i;memset(bz,0,sizeof(bz)); for (j=r[i-1]+1;j<=n;j++){ if (bz[a[j]]>=0){ bz[a[j]]++;t=a[j]/qq+1; ans[i][k][t]++; if (bz[a[j]]>m){ ans[i][k][t]-=bz[a[j]]; bz[a[j]]=-1; } } if (j==r[k]) k++; } for (j=i+1;j<=ln;j++) for (k=1;k<=ln1;k++) ans[i][j][k]+=ans[i][j-1][k]; } memset(bz,0,sizeof(bz)); for (i=1;i<=test;i++){ scanf("%d%d%d",&x,&y,&z);x^=bz2*ans1;y^=bz2*ans1;z^=bz2*ans1; t=x/q+(x%q!=0)+(x%q!=1); if (y!=r[ln]) k=y/q-(y/q==ln && y!=ln*q); else k=ln; if (t>k){ b[0]=0; for (j=x;j<=y;j++)bz[a[j]]++; for (j=x;j<=y;j++)if(bz[a[j]]<=m) b[++b[0]]=a[j]; if (b[0]>=z){ sort(b+1,b+b[0]+1); printf("%d\n",b[z]);ans1=b[z]; }else printf("%d\n",n),ans1=n; for (j=x;j<=y;j++)bz[a[j]]=0; }else{ for (j=x;j<=r[t-1];j++)bz[a[j]]++,bz1[a[j]]++; for (j=r[k]+1;j<=y;j++)bz[a[j]]++,bz1[a[j]]++; dg(x,r[t-1]);dg(r[k]+1,y); num=0; for (j=1;j<=ln1;j++){ if (num+ans[t][k][j]<z) num+=ans[t][k][j]; else{ for (l=rr[j-1]+1;l<=rr[j];l++) if (sum[l][k]-sum[l][t-1]+bz1[l]<=m){ if (num+sum[l][k]-sum[l][t-1]+bz1[l]<z) num+=sum[l][k]-sum[l][t-1]+bz1[l]; else{ num=-1; printf("%d\n",l); ans1=l; break; } } break; } } if (num>=0) printf("%d\n",n),ans1=n; dg1(x,r[t-1]);dg1(r[k]+1,y); for (j=x;j<=r[t-1];j++)bz[a[j]]=bz1[a[j]]=0; for (j=r[k]+1;j<=y;j++)bz[a[j]]=bz1[a[j]]=0; } }}
阅读全文
1 0
- 【JZOJ5260】【GDOI2018模拟8.12】区间第k小
- 【JZOJ5260】【GDOI2018模拟8.12】区间第k小(分块)
- 【GDOI2018模拟8.12】区间第k小
- 【GDOI2018模拟8.12】区间第k小
- 区间第k小
- 分块 区间第k小
- 区间第k小 分块
- 【GDOI2018模拟8.12】求和
- 【GDOI2018模拟8.12】求和
- zoj2112(单点修改区间第K小)
- 主席树模板 区间第k小
- 【JZOJ 5260】 区间第k小
- 【GDOI2018模拟7.14】小奇的糖果
- [JZOJ5261]【GDOI2018模拟8.12】求和
- 【JZOJ5262】【GDOI2018模拟8.12】树
- 【模拟】找第k小的数
- poj2761——treap,区间第K小值
- 查找给定区间内第K大/小的数
- Mysql的字段类型,查询语句,高级操作
- DNA repair HDU
- Redis系列学习(四)之jedis工具类
- DIV标签设置浮动后,对下一个DIV标签width的影响
- 《七大排序算法》(二)之简单选择排序(Java实现)
- 【JZOJ5260】【GDOI2018模拟8.12】区间第k小
- 漫谈大数据
- 利用PHP GD库生成位图
- 【BZOJ1085】【SCOI2005】骑士精神(IDA*)
- Win10/Win8使用ADB连接不上Android设备,设备管理器出现黄色叹号解决方案
- hdu1083 Courses
- 剑指offer_二叉树---二叉树中和为某一值的路径
- Android启动模式小结
- jzoj5317 【清华集训2017模拟8.19】func (寻找性质)