您的位置:首页 > 其它

HDU 5145 (莫队算法)

2016-04-27 20:55 295 查看


NPY and girls

Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 631    Accepted Submission(s): 197

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 are in different classes(some
girls may be in the same class).And the i-th girl is in class ai.NPY wants to visit his girls frequently.Each time he visits some girls numbered consecutively from L to R in some order. He can only visit one girl every time he goes into a classroom,otherwise
the girls may fight with each other(-_-!).And he can visit the class in any order.

Here comes the problem,(NPY doesn't want to learn how to use excavator),he wonders how many different ways there can be in which he can visit his girls.The different ways are different means he visits these classrooms in different order.

 

Input

The first line contains the number of test cases T(1≤T≤10).

For each test case,there are two integers n,m(0<n,m≤30000) in
the first line.N is the number of girls,and M is the number of times that NPY want to visit his girls.

The following single line contains N integers, a1,a2,a3,…,an,
which indicates the class number of each girl. (0<ai≤30000)

The following m lines,each line contains two integers l,r(1≤l≤r≤n),which
indicates the interval NPY wants to visit.

 

Output

For each visit,print how many ways can NPY visit his girls.Because the ans may be too large,print the ans mod 1000000007.

 

Sample Input

2
4 2
1 2 1 3
1 3
1 4
1 1
1
1 1

 

Sample Output

3
12
1

 

题意:给出一个序列,然后m个询问,每次询问[l,r]中的方案数,方案数指的是所有询问

区间中数字的组合数.

因为C(m+1,n+1)=C(m,n)*(m+1)/(n+1),所以增加和删除就可以O(1)求出来辣.

#include <bits/stdc++.h>
using namespace std;
#define maxn 31111
#define mod 1000000007

int pos[maxn];
int n, m, k;
long long cnt[maxn];
long long ans[maxn], tmp[maxn];
struct node {
int l, r, id;
bool operator < (const node &a) const {
return pos[l] < pos[a.l] || (pos[l] == pos[a.l] && r < a.r);
}
long long ans;
} p[maxn];
int a[maxn];
long long cur;

bool cmp (const node &a, const node &b) {
return a.id < b.id;
}

int l, r;
long long rev[maxn];
void add (int pos) {
int n = cnt[a[pos]], m = r-l;
cnt[a[pos]]++;
cur = cur * (m+1)%mod * rev[n+1]%mod;
}

void del (int pos) {
cnt[a[pos]]--;
int n = cnt[a[pos]], m = r-l;
cur = cur * (n+1)%mod * rev[m+1]%mod;
}

void init () {
rev[1] = 1;
for (int i = 2; i < maxn; i++){
rev[i] = (long long)(mod - mod/i) * rev[mod % i] % mod;
}
}

int main () {
//freopen ("in.txt", "r", stdin);
init ();
int t;
scanf ("%d", &t);
while (t--) {
scanf ("%d%d", &n, &m);
for (int i = 1; i <= n; i++) {
scanf ("%d", &a[i]);
}
int block = ceil (sqrt (n*1.0));
for (int i = 1; i <= n; i++) pos[i] = (i-1)/block;

for (int i = 0; i < m; i++) {
scanf ("%d%d", &p[i].l, &p[i].r);
p[i].id = i;
}
sort (p, p+m);
l = 1, r = 1;
cur = 0;
memset (cnt, 0, sizeof cnt);
add (1);
cur = 1;

for (int i = 0; i < m; i++) {
while (r > p[i].r) {
del (r);
r--;
}
while (r < p[i].r) {
r++;
add (r);
}
while (l > p[i].l) {
l--;
add (l);
}
while (l < p[i].l) {
del (l);
l++;
}
ans[p[i].id] = cur;
}
for (int i = 0; i < m; i++) {
printf ("%lld\n", ans[i]);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: