[BZOJ3809]Gty的二逼妹子序列(莫队+分块)
2016-04-26 23:17
435 查看
题目描述
传送门题解
莫队+树状数组的思路很显然,但是时间O(mn√log2n)莫队+权值分块的做法比较优越。将权值分块之后修改可以做到O(1)查询O(n√)
代码
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<cmath> using namespace std; const int max_n=1e5+5; const int max_m=1e6+5; const int max_sqrt=350; int n,m,t,num,ans; int a[max_n],val[max_n],sum[max_sqrt]; struct hp{int l,r,a,b,id,final;}q[max_m]; inline int cmp(hp a,hp b){ int num1,num2; if (a.l%t==0) num1=a.l/t; else num1=a.l/t+1; if (b.l%t==0) num2=b.l/t; else num2=b.l/t+1; return num1<num2||(num1==num2&&a.r<b.r); } inline int ask(int l,int r){ int ans=0,k,lrange,rrange,numl,numr; if (l%t==0) numl=l/t; else numl=l/t+1; if (r%t==0) numr=r/t; else numr=r/t+1; if (numl==numr){ for (int i=l;i<=r;++i) if (val[i]) ans++; return ans; } lrange=numl+1; k=numl*t; for (int i=l;i<=k;++i) if (val[i]) ans++; k=(numr-1)*t+1; for (int i=k;i<=r;++i) if (val[i]) ans++; rrange=numr-1; for (int i=lrange;i<=rrange;++i) ans+=sum[i]; return ans; } int main(){ scanf("%d%d",&n,&m); t=(int)sqrt(n); for (int i=1;i<=n;++i) scanf("%d",&a[i]); for (int i=1;i<=m;++i) scanf("%d%d%d%d",&q[i].l,&q[i].r,&q[i].a,&q[i].b),q[i].id=i; sort(q+1,q+m+1,cmp); for (int i=q[1].l;i<=q[1].r;++i){ if (a[i]%t==0) num=a[i]/t; else num=a[i]/t+1; ++val[a[i]]; if (val[a[i]]==1) ++sum[num]; } ans=ask(q[1].a,q[1].b); q[q[1].id].final=ans; for (int i=2;i<=m;++i){ if (q[i-1].l<q[i].l) for (int j=q[i-1].l;j<q[i].l;++j){ if (a[j]%t==0) num=a[j]/t; else num=a[j]/t+1; --val[a[j]]; if (!val[a[j]]) --sum[num]; } if (q[i-1].l>q[i].l) for (int j=q[i-1].l-1;j>=q[i].l;--j){ if (a[j]%t==0) num=a[j]/t; else num=a[j]/t+1; ++val[a[j]]; if (val[a[j]]==1) ++sum[num]; } if (q[i-1].r<q[i].r) for (int j=q[i-1].r+1;j<=q[i].r;++j){ if (a[j]%t==0) num=a[j]/t; else num=a[j]/t+1; ++val[a[j]]; if (val[a[j]]==1) ++sum[num]; } if (q[i-1].r>q[i].r) for (int j=q[i-1].r;j>q[i].r;--j){ if (a[j]%t==0) num=a[j]/t; else num=a[j]/t+1; --val[a[j]]; if (!val[a[j]]) --sum[num]; } ans=ask(q[i].a,q[i].b); q[q[i].id].final=ans; } for (int i=1;i<=m;++i) printf("%d\n",q[i].final); }
相关文章推荐
- CommonUtil类
- linux下yum安装mysql步骤
- UML
- nefu 1144 线段重叠
- 关于scanf与gets的区别
- IMF传奇行动第83课:Spark Streaming第二课:用Scala和Java二种方式实战Spark Streaming开发
- vim工具
- Ioc容器Autofac系列(3)-- 三种注册组件的方式
- 标题背景加蓝色
- java.lang.ClassNotFoundException: net.sf.cglib.proxy.Callback
- 1001. 二哥摘苹果
- 在OS X 上安装MongoDB
- 002如何构建hadoop集群环境?
- bzoj 2060: [Usaco2010 Nov]Visiting Cows 拜访奶牛(树形DP)
- Windwos 08R2_DNS+AD安装图文
- c++第四次实验
- LocalNotification 与远程通知的是如何操作的?
- 随心所欲的DateTime显示格式
- TLD学习(3) arthurv版TLD
- Mysql cluster初学