[洛谷P1972][题解][SDOI2009]HH的项链

别碰我!

自己还是太蒟了……

看了好久,最后抄参考题解打出来的……

前面的可能影响后面的,所以按照询问右端点排序

这时候维护一个前缀和数组就可以了,

那么问题又来了,去重?

可以这样,从前往后枚举,如果被加过了就在前面去掉

具体看代码(题目毒瘤导致卡常卡了好几遍):

 

 1 #include<bits/stdc++.h>
 2 #define rint register int
 3 #define lowbit(x) (x&(-x))
 4 using namespace std;
 5 int n,m,t[1000010],a[1000010],vis[1000010],ot[1000010];
 6 inline int rd(){
 7     int x=0,f=1;
 8     char c=getchar();
 9     while(c<'0'||c>'9'){
10         if(c=='-')f=-1;
11         c=getchar();
12     }
13     while(c>='0'&&c<='9'){
14         x=x*10+c-'0';
15         c=getchar();
16     }
17     return x*f;
18 }
19 struct Question {
20     int l,r,id;
21 }q[1000010];
22 inline bool cmp(Question a,Question b){
23     return a.r<b.r;
24 }
25 inline void AddPoint(int x,int add){
26     while(x<=n){
27         t[x]+=add;
28         x+=lowbit(x);
29     }
30 }
31 inline int Sum(int x){
32     int ans=0;
33     while(x){
34         ans+=t[x];
35         x-=lowbit(x);
36     }
37     return ans;
38 }
39 inline int QuerySec(int l,int r){
40     return Sum(r)-Sum(l-1);
41 }
42 int main(){
43     n=rd();
44     for(rint i=1;i<=n;i++)a[i]=rd();
45     cin>>m;
46     for(rint i=1;i<=m;i++){
47         q[i].l=rd();
48         q[i].r=rd();
49         q[i].id=i;
50     }
51     sort(q+1,q+1+m,cmp);
52     int now=1;
53     for(rint i=1;i<=m;i++){
54         for(rint j=now;j<=q[i].r;j++){
55             if(vis[a[j]]){//如果加过了 
56                 AddPoint(vis[a[j]],-1);//去掉 
57             }
58             AddPoint(j,1);//新加上的 
59             vis[a[j]]=j;//标记 
60         }
61         now=q[i].r+1;
62         ot[q[i].id]=QuerySec(q[i].l,q[i].r);//注意顺序 
63     }
64     for(rint i=1;i<=m;i++)cout<<ot[i]<<endl;
65     return 0;
66 }

 

因为是离线枚举所以千万不要忘了存回去!

 

上一篇:API经济最主要是学会调用API


下一篇:数论训练之一