Orz lct1999

  好神的做法。。。

  先看下暴力的做法:对于区间[l,r],我们依次扫过去,如果这个数是第一次出现,那么我们种类数+1。

  我们发现:区间中相同的几个数,只有最左边那个才对答案有贡献。

  那么我们O(n)预处理一个next数组,满足a[i]=a[next[i]],且i~next[i]这一段中没有与a[i]相等的数。。。。其实就是 i 右边第一个跟a[i]相等的值的下标啦。。

  再回头看下我们的询问:对答案有贡献的数的特点是:它在整个序列中第一次出现,或者它是区间外某个数的next。在区间中再次出现的数,next指向它的数也一定也在区间中。

  

  那么我们处理查询[l,r]时,我们可以将[1,l-1]的next[i]对答案的贡献+1,也就是我们维护一个ans数组,对ans[next[i]]++

  答案就是ans[r]-ans[l-1](都是前缀和)

  对询问进行左端点排序,树状数组维护一下即可……

  (然而感觉蒟蒻并没有讲清楚……大家可以去看zyf神犇的blog:http://www.cnblogs.com/zyfzyf/p/3935617.html

 1 /**************************************************************
 2     Problem: 1878
 3     User: Tunix
 4     Language: C++
 5     Result: Accepted
 6     Time:920 ms
 7     Memory:5768 kb
 8 ****************************************************************/
 9  
10 //BZOJ 1878
11 #include<cstdio>
12 #include<cstring>
13 #include<cstdlib>
14 #include<iostream>
15 #include<algorithm>
16 #define rep(i,n) for(int i=0;i<n;++i)
17 #define F(i,j,n) for(int i=j;i<=n;++i)
18 #define D(i,j,n) for(int i=j;i>=n;--i)
19 #define pb push_back
20 using namespace std;
21 typedef long long LL;
22 inline int getint(){
23     int r=1,v=0; char ch=getchar();
24     for(;!isdigit(ch);ch=getchar()) if (ch=='-') r=-1;
25     for(; isdigit(ch);ch=getchar()) v=v*10-'0'+ch;
26     return r*v;
27 }
28 const int N=50010,M=200010;
29 /*******************template********************/
30 int n,m,num,a[N],c[N],now[N],fi[N],next[N],ans[M];
31 struct que{int l,r,num;}q[M];
32 bool operator < (const que &a,const que &b){return a.l<b.l;}
33  
34 int b[N],d[N];
35 void add(int x){
36     d[x]++;
37     if (!x) return;
38     for(int i=x;i<=n;i+=i&(-i)) b[i]++;
39 }
40 int sum(int x){
41     int r=0;
42     for(int i=x;i;i-=i&(-i)) r+=b[i];
43     return r;
44 }
45 void init(){
46     n=getint();
47     F(i,1,n) c[i]=a[i]=getint();
48     sort(c+1,c+n+1);
49     num=unique(c+1,c+n+1)-c-1;
50     F(i,1,n){
51         a[i]=lower_bound(c+1,c+num+1,a[i])-c;
52         if (now[a[i]]){
53             next[now[a[i]]]=i;
54             now[a[i]]=i;
55         }else{
56             add(i);
57             now[a[i]]=i;
58         }
59     }
60     m=getint();
61     F(i,1,m) q[i].l=getint(),q[i].r=getint(),q[i].num=i;
62 }
63 void solve(){
64     sort(q+1,q+m+1);
65     int now=1;
66     F(i,1,m){
67         while(now<q[i].l){
68             add(next[now]);
69             now++;
70         }
71         ans[q[i].num]=sum(q[i].r)-sum(q[i].l-1);
72     }
73     F(i,1,m) printf("%d\n",ans[i]);
74 }
75 int main(){
76 #ifndef ONLINE_JUDGE
77     freopen("1878.in","r",stdin);
78     freopen("1878.out","w",stdout);
79 #endif
80     init();
81     solve();
82     return 0;
83 }
View Code

相关文章:

  • 2021-08-17
  • 2022-12-23
  • 2022-01-16
  • 2022-03-07
  • 2021-12-13
  • 2021-06-29
  • 2021-09-12
  • 2021-06-15
猜你喜欢
  • 2021-12-12
  • 2022-01-17
  • 2022-02-02
  • 2022-12-23
  • 2021-08-08
  • 2021-08-07
相关资源
相似解决方案