您的位置:首页 > 其它

HDU 5145 NPY and girls (莫队算法)

2014-12-14 12:07 274 查看
题目: LINK

题目给定一个长度为n的序列,给出m个查询,[L,R],求区间内重排的个数。计算很简单 (R - L -1)! / (II 每个相同数字个数的阶乘)

即使裸着排序,递推会TLE。

可以使用莫队算法,分块的写法比较简单。

这样写就是分块,每一块的大小为sqrt(n),L按照块号排序,之后按照R排序。之后的写法和之前写的一样。

我自己估算的这样搞的复杂度约为 O(m*sqrt(n) + n*sqrt(n)); 

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <cmath>
#include <queue>
#include <map>
#include <set>
using namespace std;
#define INF 1000000000
typedef __int64 LL;
#define N 31111
LL t, n, m, num
, G;
const LL mod = 1000000007;
struct node {
LL l, r, id;
}p
;
LL ans
, f
, ff
, cou
;
int cmp(node x, node y) {
if(x.l / G != y.l / G) return x.l / G < y.l / G;
return x.r < y.r ;
}
LL pow_(LL x, LL y, LL mm) {
LL ret = 1;
while(y) {
if(y&1) {
ret *= x; ret %= mm;
}
y >>= 1;
x *= x; x %= mm;
}
return ret;
}
void init() {
f[0] = ff[0] = 1;
for(LL i = 1; i < N; i++) {
f[i] = f[i-1] * i; f[i] %= mod;
ff[i] = pow_(f[i], mod - 2, mod); // get Inv();
}
}
void work() {
LL tmp = 1;
memset(cou, 0, sizeof(cou));
int L = 1, R = 0;
for(int i = 1; i <= m; i++) {
while(R < p[i].r) {
R ++;
tmp = tmp * f[cou[num[R]]] % mod;
cou[num[R]] ++;
tmp = tmp * ff[cou[num[R]]] % mod;
}
while(R > p[i].r) {
tmp = tmp * f[cou[num[R]]] % mod;
cou[num[R]] --;
tmp = tmp *ff[cou[num[R]]] % mod;
R --;
}
while(L < p[i].l) {
tmp = tmp * f[cou[num[L]]] % mod;
cou[num[L]] --;
tmp = tmp * ff[cou[num[L]]] % mod;
L ++;
}
while(L > p[i].l) {
L --;
tmp = tmp * f[cou[num[L]]] % mod;
cou[num[L]] ++;
tmp = tmp * ff[cou[num[L]]] % mod;
}
ans[p[i].id] = f[R - L + 1] * tmp % mod;
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif // ONLINE_JUDGE
init();
scanf("%I64d", &t);
while(t--) {
scanf("%I64d%I64d", &n, &m);
for(int i = 1; i <= n; i++) {
scanf("%I64d", &num[i]);
}
for(int i = 1; i <= m; i++) {
scanf("%I64d%I64d", &p[i].l, &p[i].r);
p[i].id = i;
}
G = (int) sqrt(1.0 * n);
sort(p+1, p+1+m, cmp);
work();
for(int i = 1; i <= m; i++) {
printf("%I64d\n", ans[i]);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: