[bzoj4241] 历史研究
2016-04-11 13:57
567 查看
分块大法好。。
这题就是个带权的区间众数。。。离散化一下就是普通的区间众数了。
分成根号n块,预处理mx[i][j]表示第i块~第j块 这段区间里的众数,pr[i][j]表示前i块里,数字j出现了多少次。
所以每个询问的答案,要么是整块里的众数,要么是两侧零散的数。
整块里面每个数出现的次数就是pr[],两侧的出现次数就直接暴力累加。
分块果然好写= =
View Code
这题就是个带权的区间众数。。。离散化一下就是普通的区间众数了。
分成根号n块,预处理mx[i][j]表示第i块~第j块 这段区间里的众数,pr[i][j]表示前i块里,数字j出现了多少次。
所以每个询问的答案,要么是整块里的众数,要么是两侧零散的数。
整块里面每个数出现的次数就是pr[],两侧的出现次数就直接暴力累加。
分块果然好写= =
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #define ll long long using namespace std; const int maxn=100233; struct zs{ int v,pos; }a[maxn]; ll b[maxn],cnt; int l[333],r[333],id[maxn]; int mx[333][333],pr[333][maxn]; int num[maxn],mp[maxn]; int i,j,k,n,m,kuai,x,y; int ra;char rx; inline int read(){ rx=getchar(),ra=0; while(rx<'0'||rx>'9')rx=getchar(); while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra; } bool cmp(zs a,zs b){return a.v==b.v?a.pos<b.pos:a.v<b.v;} inline ll query(int x,int y){ register int i;; int idl=(x+kuai-1)/kuai,idr=(y+kuai-1)/kuai, ans=mx[idl+1][idr-1]; if(idl==idr){ for(i=x;i<=y;i++) ++num[mp[i]],ans=b[ans]*num[ans]<b[mp[i]]*num[mp[i]]?mp[i]:ans; ll sum=b[ans]*num[ans]; for(i=x;i<=y;i++)num[mp[i]]=0; return sum; } for(i=x;i<=r[idl];i++)++num[mp[i]]; for(i=l[idr];i<=y;i++)++num[mp[i]]; ll sum=b[ans]*( pr[idr-1][ans]-pr[idl][ans]+num[ans] );//printf(" sum:%lld %d %d %d\n",sum,idl,idr,pr[idr-1][ans]-pr[idl][ans]+num[ans]); for(i=x;i<=r[idl];num[mp[i]]=0,i++)if(num[mp[i]]) if( b[mp[i]]*( pr[idr-1][mp[i]]-pr[idl][mp[i]]+num[mp[i]] ) > sum )ans=mp[i],sum=b[ans]*( pr[idr-1][ans]-pr[idl][ans]+num[ans] ); for(i=l[idr];i<=y;num[mp[i]]=0,i++)if(num[mp[i]]) if( b[mp[i]]*( pr[idr-1][mp[i]]-pr[idl][mp[i]]+num[mp[i]] ) > sum )ans=mp[i],sum=b[ans]*( pr[idr-1][ans]-pr[idl][ans]+num[ans] ); return sum; } int main(){ register int j,k; n=read(),m=read(),kuai=min(n,323);//kuai=1; for(i=1;i<=n;i++)a[i].v=mp[i]=read(),a[i].pos=i,id[i]=(i+kuai-1)/kuai; for(i=1;i<=id ;i++)l[i]=(i-1)*kuai+1,r[i]=min(n,i*kuai); sort(a+1,a+1+n,cmp); for(i=1;i<=n;mp[a[i].pos]=cnt,pr[id[a[i].pos]][cnt]++,i++) if(a[i].v!=a[i-1].v)b[++cnt]=a[i].v; for(i=1;i<=id ;i++) for(mx[i][i]=mp[l[i]],j=l[i]+1;j<=r[i];j++)if(b[mp[j]]*pr[i][mp[j]]>b[mx[i][i]]*pr[i][mx[i][i]])mx[i][i]=mp[j]; for(i=2;i<=id ;i++)for(j=1;j<=cnt;j++)pr[i][j]+=pr[i-1][j]; for(i=1;i<id ;i++){ for(j=1;j<=cnt;j++)num[j]=pr[i][j]-pr[i-1][j]; for(j=i+1;j<=id ;/*printf("mx:%d %d %lld\n",i,j,b[mx[i][j]]),*/j++) for(mx[i][j]=mx[i][j-1],k=l[j];k<=r[j];k++) num[mp[k]]++,mx[i][j]=b[mx[i][j]]*num[mx[i][j]]<b[mp[k]]*num[mp[k]]?mp[k]:mx[i][j]; } // printf(" %lld\n",b[mx[1][id ]]); memset(num,0,(cnt+1)<<2); while(m--) x=read(),y=read(), printf("%lld\n",query(x,y)); return 0; }
View Code
相关文章推荐
- 用cmd内置telnet客户端模拟http请求
- Linux下安装redis
- xshell展示服务器记录日志
- IOS学习之基于IOS7的tab bar
- jenkins相关
- 应用程序国际化和本地化
- 继承中的构造方法
- disp直接将内容输出在Matlab命令窗口中
- 没事四处闲逛,总能找到想要的!各种mark!
- BUG-Undefined symbols for architecture x86_64错误
- JAVA发送HTTP请求
- maven 添加jar包
- Apache POI 合并单元格
- 十大前端开发框架
- MFC中设备上下文的概念和继承关系图解
- bzoj 4499
- 浅谈算法和数据结构: 六 符号表及其基本实现
- Eclipse 常用快捷键
- cocoPods可能遇到的错误iOS
- jquery中$.post()方法的简单实例