HDU 5145 NPY and girls (莫队分块离线)

题目地址:HDU 5145

莫队真的好神奇。。这样的复杂度居然只有n*sqrt(n)。。。

裸的莫队分块,先离线,然后按左端点分块,按块数作为第一关键字排序,然后按r值作为第二关键字进行排序。都是从小到大,可以证明这样的复杂度只有n*sqrt(n)。然后进行块之间的转移。

代码如下:

#include <iostream>
#include <string.h>
#include <math.h>
#include <queue>
#include <algorithm>
#include <stdlib.h>
#include <map>
#include <set>
#include <stdio.h>
#include <time.h>
using namespace std;
#define LL __int64
#define pi acos(-1.0)
//#pragma comment(linker, "/STACK:1024000000")
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
const double eqs=1e-9;
const int MAXN=30000+10;
int a[MAXN];
LL ans[MAXN], inv[MAXN], ha[MAXN];
struct node
{
        int l, r, id, pos;
}fei[MAXN];
bool cmp(node x, node y)
{
        return x.pos<y.pos||(x.pos==y.pos&&x.r<y.r);
}
LL Pow(LL x, int k)
{
        LL ans=1;
        while(k){
                if(k&1) ans=ans*x%mod;
                x=x*x%mod;
                k>>=1;
        }
        return ans;
}
void init()
{
        for(int i=0;i<=30000;i++){
                inv[i]=Pow((LL)i,mod-2);
        }
}
int main()
{
        int t, n, m, i, j, l, r, k, Case=0;
        LL res;
        //freopen("1.txt","r",stdin);
        //freopen("2.txt","w",stdout);
        init();
        scanf("%d",&t);
        while(t--){
                scanf("%d%d",&n,&m);
                k=sqrt(n*1.0);
                for(i=1;i<=n;i++){
                        scanf("%d",&a[i]);
                }
                for(i=0;i<m;i++){
                        scanf("%d%d",&fei[i].l,&fei[i].r);
                        fei[i].id=i;
                        fei[i].pos=fei[i].l/k;
                }
                sort(fei,fei+m,cmp);
                l=1;r=1;
                res=1;
                memset(ha,0,sizeof(ha));
                ha[a[1]]=1;
                for(i=0;i<m;i++){
                        while(r<fei[i].r){
                                r++;
                                ha[a[r]]++;
                                res=res*(r-l+1)%mod*inv[ha[a[r]]]%mod;
                        }
                        while(r>fei[i].r){
                                res=res*ha[a[r]]%mod*inv[r-l+1]%mod;
                                ha[a[r]]--;
                                r--;
                        }
                        while(l>fei[i].l){
                                l--;
                                ha[a[l]]++;
                                res=res*(r-l+1)%mod*inv[ha[a[l]]]%mod;
                        }
                        while(l<fei[i].l){
                                res=res*ha[a[l]]%mod*inv[r-l+1]%mod;
                                ha[a[l]]--;
                                l++;
                        }
                        ans[fei[i].id]=res;
                }
                for(i=0;i<m;i++){
                        printf("%I64d\n",ans[i]);
                }
        }
        return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-21 21:17:51

HDU 5145 NPY and girls (莫队分块离线)的相关文章

hdu 5145 NPY and girls 莫队

题意: 给你1-n属于的班级 给你一个[l,r]区间 问你如果要访问这个区间内所有的女生 有多少种走不同教室的方法 思路: 和小z差不多 只不过这个维护的是阶乘 找出来公式之后莫队直接离线处理 莫队更多的是离线排序优化的思想 把所有查询排序处理 然后逐个处理 可以应用到很多方面 1 #include<bits/stdc++.h> 2 #define cl(a,b) memset(a,b,sizeof(a)) 3 #define debug cerr<<#a<<"

HDU 5145 NPY and girls 莫队算法

对于这类区间查询的问题,如果可以用O(1)的复杂度推到一个曼哈顿距离为1的另外区间的话,就可以直接用莫队算法搞. 从网上搜到的有两种搞法.第一种是先建立曼哈顿距离最小生成树,然后直接dfs遍历整棵树来求解的. 还有一种是先分块,然后把查询按照块的编号为第一关键字,右边界为第二关键字排序,排序直接直接暴力转移. 这样做的复杂度是n * sqrt(n),后面那个sqrt(n)取决于是怎么分块的. 仔细想想感觉这样子搞复杂度差不多就是这样,因为在同一个块中的复杂度怎么搞都是sqrt(n)级别的,就算是

HDU 5145 NPY and girls(莫队算法+乘法逆元)

[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5145 [题目大意] 给出一个数列,每次求一个区间数字的非重排列数量.答案对1e9+7取模. [题解] 我们发现每次往里加入一个新的数字或者减去一个新的数字,前后的排列数目是可以通过乘除转移的,所以自然想到用莫队算法处理.因为答案要求取模,所以在用除法的时候要计算逆元. [代码] #include <cstdio> #include <algorithm> #include <

hdu NPY and girls 莫队+逆元

NPY and girls Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Problem Description NPY's girlfriend blew him out!His honey doesn't love him any more!However, he has so many girlfriend candidates.Because there are to

莫队+分块 BZOJ 3809

3809: Gty的二逼妹子序列 Time Limit: 80 Sec  Memory Limit: 28 MBSubmit: 1634  Solved: 482[Submit][Status][Discuss] Description Autumn和Bakser又在研究Gty的妹子序列了!但他们遇到了一个难题. 对于一段妹子们,他们想让你帮忙求出这之内美丽度∈[a,b]的妹子的美丽度的种类数. 为了方便,我们规定妹子们的美丽度全都在[1,n]中. 给定一个长度为n(1<=n<=100000)

BZOJ 4129 Haruna’s Breakfast 带修改树上莫队+分块

题目大意:给定一棵树,每个点有一个非负点权,支持下列操作 1.修改某个点的点权 2.查询某条链上的mex 考虑链上不带修改的版本,我们可以用莫队+分块来搞(链接戳这里) 现在到了树上带修改,果断糖果公园 本来抱着逗比的心态写了一发结果1.4s过了 跟糖果公园的80s完全不成正比啊0.0 #include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <

[BZOJ 3585] mex 【莫队+分块】

题目链接:BZOJ - 3585 题目分析 区间mex,即区间中没有出现的最小自然数. 那么我们使用一种莫队+分块的做法,使用莫队维护当前区间的每个数字的出现次数. 然后求mex用分块,将权值分块(显然mex 一定小于等于 n ,大于 n 的权值没有意义,可以直接忽略),每块大小 sqrt(n) . 然后区间中的某个数的数量被减到0的时候就将它所在的块的种类计数减一,添加数的时候类似. 然后枚举每个块,找到最小的中间有数不存在的块(即种类数小于块中的数的种数),然后到这个快里直接从小一个一个找到

Hdu5145NPY and girls莫队算法

Problem Description NPY's girlfriend blew him out!His honey doesn't love him any more!However, he has so many girlfriend candidates.Because there are too many girls and for the convenience of management, NPY numbered the girls from 1 to n.These girls

【BZOJ 3809】 3809: Gty的二逼妹子序列 (莫队+分块)

3809: Gty的二逼妹子序列 Time Limit: 80 Sec  Memory Limit: 28 MBSubmit: 1728  Solved: 513 Description Autumn和Bakser又在研究Gty的妹子序列了!但他们遇到了一个难题. 对于一段妹子们,他们想让你帮忙求出这之内美丽度∈[a,b]的妹子的美丽度的种类数. 为了方便,我们规定妹子们的美丽度全都在[1,n]中. 给定一个长度为n(1<=n<=100000)的正整数序列s(1<=si<=n),对