HYSBZ 2038 莫队算法
来源:互联网 发布:hbase快速清空表数据 编辑:程序博客网 时间:2024/05/16 02:48
题意
中文题,不解释
题解
莫队入门题。其实莫队就是暴力,只不过利用了上一次计算的结果,同时对区间进行合理分块,可以使得复杂度可以降低到O(N^(3/2))。题目要求求区间内任意选两个数,相同的概率。如果时间宽松一点,对于稍微有点数学基础的选手都可以在5分钟内写出相应代码,组合数公式随便搞一下就可以。
对于这道题就不行了,不但不能暴力,并且用什么数据结构都会感觉不舒服(会各种树套树的大牛可以无视此句。)不过我们可以用莫队算法优化一下暴力流程,我们可以将整个数轴分为M块,每块的大小为sqrt(MX))(MX为数轴最大值)然后我们可以进行排序,在同一块的元素放在一起。
至于分块的原因其实很简单,如果直接排序的话,很容易被卡。比如说(100,1),(50,1000),(1,1)这样一个样例。由于莫队是利用上一次结果进行转移,那么这个样例就需要先从1转移到1000,然后再从1000转移到1。明显可以看出来这样是不好的。所以我们可以允许X在一定范围内非单增,比如我们可以把一块设置为100,那么在这一块内便根据Y排序,那么便会排列成(100,1),(1,1),(50,1000),这样的话转移变少了1000次,优化很明显。
解决了分快的问题,莫队算法的核心基本就解决了。另外的话,莫队算法还有一个核心就是,对于每一个查询,不直接计算,而是通过上一个状态转移的这一个状态来计算值,这样分块的作用才能达到。
代码
#include <iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<vector>#include<cmath>#include<queue>#include<string>#include<set>#include<map>#include<bitset>#include<stack>#include<string>#define UP(i,l,h) for(int i=l;i<h;i++)#define DOWN(i,h,l) for(int i=h-1;i>=l;i--)#define W(a) while(a)#define MEM(a,b) memset(a,b,sizeof(a))#define LL long long#define INF 0x3f3f3f3f3f3f3f3f#define MAXN 50010#define MOD 1000000007#define EPS 1e-3#define int LLusing namespace std;struct Node{ int l,r,id,val,all;};int c[MAXN],pos[MAXN],cnt[MAXN],val;Node nodes[MAXN];int n,m;bool cmp(Node a,Node b){ return pos[a.l]==pos[b.l]?a.r<b.r:a.l<b.l;}bool cmp1(Node a,Node b){ return a.id<b.id;}void update(int p,int add){ val-=cnt[p]*(cnt[p]-1)/2; cnt[p]+=add; val+=cnt[p]*(cnt[p]-1)/2;;}void solve(){ MEM(cnt,0); int l=1,r=1; val=0; update(c[1],1); UP(i,0,m){ nodes[i].all=(nodes[i].r-nodes[i].l+1)*(nodes[i].r-nodes[i].l)/2; for(;l<nodes[i].l;l++) update(c[l],-1); for(;l>nodes[i].l;l--) update(c[l-1],1); for(;r>nodes[i].r;r--) update(c[r],-1); for(;r<nodes[i].r;r++) update(c[r+1],1); nodes[i].val=val; }}main() { scanf("%lld%lld",&n,&m); UP(i,1,n+1) scanf("%lld",&c[i]); int mx=0; UP(i,0,m){ scanf("%lld%lld",&nodes[i].l,&nodes[i].r); nodes[i].id=i; mx=max(mx,nodes[i].l); } int q=sqrt(mx); UP(i,1,mx+1) pos[i]=i/q; sort(nodes,nodes+m,cmp); solve(); sort(nodes,nodes+m,cmp1); UP(i,0,m){ int g=__gcd(nodes[i].val,nodes[i].all); if(g==0) printf("0/1\n"); else printf("%lld/%lld\n",nodes[i].val/g,nodes[i].all/g); }}
阅读全文
0 0
- HYSBZ 2038 莫队算法
- HYSBZ 2038 小z的袜子(hose) 莫队算法
- HYSBZ 2038 小Z的袜子 莫队算法
- HYSBZ 2038 小Z的袜子(hose) (莫队算法)
- 文章标题 HYSBZ 2038 : 小Z的袜子(hose) (莫队算法)
- HYSBZ 2565 Manacher算法
- HYSBZ
- HYSBZ
- HYSBZ
- HYSBZ
- HYSBZ
- HYSBZ
- HYSBZ
- HYSBZ
- HYSBZ
- HYSBZ
- HYSBZ
- HYSBZ
- 书单
- Java JSON解析工具类(支持泛型)
- 解决办法:Android Studio报错“Error:Failed to open zip file.”
- C++从入门到入坟
- R语言:leaflet包做地图展示
- HYSBZ 2038 莫队算法
- 接口和抽象类:Interface、abstract
- 欢迎使用CSDN-markdown编辑器
- ZooKeeper_4_Java操作ZK_创建会话
- 数据库-sql语句
- table的默认宽度之变化
- MySql中的数据类型
- 进阶之路——二进制与格雷码的相互转换模块设计
- Java技术图谱