nyoj 945 Just do it(莫队算法)

来源:互联网 发布:java 异常处理 编辑:程序博客网 时间:2024/06/16 21:00

Just do it

时间限制:2000 ms  |  内存限制:65535 KB
难度:4
描述
蚂蚁终于忍受不了宇宙总部要回地球了,它叮嘱我不要再编它的故事了,
有啥事直接说,有啥问题直接问就好了,它相信大家都能替他解决的,
毕竟都解决了不少问题了。
好,这次就直接说问题
求一个序列的某个区间中出现了多少不相同的数字。对于一个序列会询问很多很多次。

输入
第一行一个整数T,表示T组数据 (T < 10)
每组数据第1行一个整数 N 表示第2行有 N 个整数ai (N <= 30000, 1 <= ai <= 1000000)
第3行一个整数 M 表示有 M 次询问的区间(M <= 200000)
第4行开始往后M行每行两个整数a b,表示询问的区间[a,b] (1 <= a <= b <= n)
输出
每组数据M行,输出表示结果
样例输入
151 1 2 1 331 52 43 5
样例输出
323
提示

Huge inpiut ,please use scanf to read.


解题思路:区间问题,而且又没有更新,莫队算法正适合处理这类情况,如果比较熟悉莫队的话就是水题啦。。

#include<iostream>#include<cstdio>#include<cstring>#include<map>#include<cmath>#include<algorithm>using namespace std;const int maxn = 300005;const int maxm = 200005;int n,m,block,a[maxn],res[maxm];int Map[1000005];struct Node{int l,r,id;bool operator < (const Node &rhs) const{if(l / block == rhs.l / block)return r / block < rhs.r / block;return l / block < rhs.l / block;}}q[maxm];void solve(){block = sqrt(n + 0.5);sort(q+1,q+1+m);int ans = 0,l = 1,r = 0;for(int i = 1; i <= m; i++){if(q[i].l == q[i].r){res[q[i].id] = 1;continue;}while(l < q[i].l){Map[a[l]]--;if(Map[a[l]] == 0) ans--;l++;}while(l > q[i].l){l--;Map[a[l]]++;if(Map[a[l]] == 1) ans++;}while(r < q[i].r){r++;Map[a[r]]++;if(Map[a[r]] == 1) ans++;}while(r > q[i].r){Map[a[r]]--;if(Map[a[r]] == 0) ans--;r--;}res[q[i].id] = ans;}for(int i = 1; i <= m; i++)printf("%d\n",res[i]);}int main(){int t;scanf("%d",&t);while(t--){memset(Map,0,sizeof(Map));scanf("%d",&n);for(int i = 1; i <= n; i++)scanf("%d",&a[i]);scanf("%d",&m);for(int i = 1; i <= m; i++){scanf("%d %d",&q[i].l,&q[i].r);q[i].id = i;}solve();}return 0;}


0 0
原创粉丝点击