HH的项链
这道题在线不好做,但是可以离线......
就是把所有的询问都读进来,按照r排序,
扫描原序列,并且记录这种颜色上一次出现的位置,
这样每次add(i,1) add(last[val[i]],-1) (last[val[i]]!=0)
如果是一个询问的左端点,就利用树状数组的前缀和进行统计
这道题不好做的地方就在于一个颜色重复出现多次不好用前缀和计算,而一个同样的颜色如果在右边出现了,左边的可以不计,这就是这个解法的开始,
很巧妙啊......
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 using namespace std; 7 const int maxn=1000119; 8 int n,m; 9 int val[maxn],last[maxn],c[maxn]; 10 int ans[maxn]; 11 struct Node{ 12 int l,r,id,ans; 13 }node[maxn]; 14 bool cmp(Node a,Node b){ 15 return a.r<b.r; 16 } 17 bool cm(Node a,Node b){ 18 return a.id<b.id; 19 } 20 int lowbit(int x){ 21 return x&(-x); 22 } 23 int sum(int x){ 24 int ret=0; 25 for(int i=x;i>0;i-=lowbit(i)) ret+=c[i]; 26 return ret; 27 } 28 void add(int pos,int val){ 29 for(int i=pos;i<=n;i+=lowbit(i)) c[i]+=val; 30 } 31 int main(){ 32 cin>>n; 33 for(int i=1;i<=n;i++) cin>>val[i]; 34 cin>>m; 35 for(int i=1;i<=m;i++){ 36 int l,r;cin>>l>>r; 37 node[i].l=l;node[i].r=r;node[i].id=i; 38 } 39 sort(node+1,node+m+1,cmp); 40 int j=1; 41 for(int i=1;i<=n;i++){ 42 if(last[val[i]]!=0) add(last[val[i]],-1); 43 add(i,1); 44 while(i==node[j].r){ 45 node[j].ans=sum(node[j].r)-sum(node[j].l-1); 46 j++; 47 } 48 last[val[i]]=i; 49 } 50 sort(node+1,node+m+1,cm); 51 for(int i=1;i<=m;i++) cout<<node[i].ans<<endl; 52 }