洛谷P1972:[SDOI2009]HH的项链(莫队/线段树)

来源:互联网 发布:vscode 护眼主题 编辑:程序博客网 时间:2024/05/29 07:51

题目传送门:https://www.luogu.org/problem/show?pid=1972

分析:本题有很多种做法,有O(n*log(n))的线段树,也有O(n*sqrt(n))的莫队。线段树的做法:

http://blog.csdn.net/kscla/article/details/70227098

下面贴一下莫队的代码(其实就是个暴力,注意每一次要先让R指针右移,再移动L指针,不然可能会出现L>R的情况,然后WA):

#include<iostream>#include<string>#include<cstring>#include<cmath>#include<cstdio>#include<cstdlib>#include<stdio.h>#include<algorithm>using namespace std;const int maxn=50010;const int maxm=200100;const int maxv=1000010;struct data{int L,R,t;} ask[maxm];int a[maxn];int num[maxv];int temp[maxm];int n,m;int sn;int Get(int x){if (!x) return 0;return (x-1)/sn+1;}bool Comp(data x,data y){int dx=Get(x.L);int dy=Get(y.L);return ( dx<dy || ( dx==dy && x.R<y.R ) );}int main(){freopen("c.in","r",stdin);freopen("c.out","w",stdout);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",&ask[i].L,&ask[i].R);ask[i].t=i;}sn=floor( sqrt( (double)n ) );sort(ask+1,ask+m+1,Comp);int nL=1,nR=0;int ans;for (int i=1; i<=m; i++){int gl=Get(ask[i-1].L);int gn=Get(ask[i].L);if (gl!=gn){while (nL<=nR){num[ a[nL] ]--;nL++;}ans=0;nL=ask[i].L;nR=nL-1;}while (nR<ask[i].R){nR++;if (!num[ a[nR] ]) ans++;num[ a[nR] ]++;}while (nL>ask[i].L){nL--;if (!num[ a[nL] ]) ans++;num[ a[nL] ]++;}while (nL<ask[i].L){num[ a[nL] ]--;if (!num[ a[nL] ]) ans--;nL++;}temp[ ask[i].t ]=ans;}for (int i=1; i<=m; i++) printf("%d\n",temp[i]);return 0;}

0 0