AtCoder Beginner Contest 174 F - Range Set Query ###K

题目链接:https://atcoder.jp/contests/abc174/tasks/abc174_f

题意:给定n个数 有q次询问 在l r 区间内有多少个不同的数
思路:考虑用离线树状数组维护 遇到有之前出现过的数就删除掉之前的位置,

这样的话需要每次跑的时候修改前面的数的时候不会影响到后面的查询  所以需要按区间的右端点从小到大排序

这样每次跑完之后剩下的结束都在后面,不会因为删除掉了前面的数而影响到答案

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 #define pb push_back
 5 const int maxn =5e5+10;
 6 const int mod=998244353;
 7 int n,q;
 8 int c[maxn];
 9 int tree[maxn];
10 int ans[maxn];
11 int vis[maxn];
12 
13 
14 int lowbits(int x)
15 {
16     return x&-x;
17 }
18 
19 void add(int x,int v)
20 {
21     while(x<=n)
22     {
23         tree[x]+=v;
24         x+=lowbits(x);
25     }
26 }
27 
28 int query(int x)
29 {
30     int ans=0;
31     while(x)
32     {
33         ans+=tree[x];
34         x-=lowbits(x);
35     }
36     return ans;
37 }
38 
39 struct ac
40 {
41     int l,r,p;
42     bool operator<(ac a)
43     {
44         return r<a.r;
45     }
46 };
47 ac a[maxn];
48 
49 int main()
50 {
51     ios::sync_with_stdio(false);
52     cin.tie(0);
53     cin>>n>>q;
54     for(int i=1;i<=n;i++)
55     {
56         cin>>c[i];
57     }
58     for(int i=1;i<=q;i++)
59     {
60         cin>>a[i].l>>a[i].r;
61         a[i].p=i;
62     }
63     sort(a+1,a+1+q);
64     int nxt=1;
65     for(int i=1;i<=q;i++)
66     {
67         for(int j=nxt;j<=a[i].r;j++)
68         {
69             if(vis[c[j]])
70                 add(vis[c[j]],-1);
71             vis[c[j]]=j;
72             add(j,1);
73         }
74         nxt=a[i].r+1;
75         ans[a[i].p]=query(a[i].r)-query(a[i].l-1);
76     }
77     for(int i=1;i<=q;i++)
78     {
79         cout<<ans[i]<<'\n';
80     }
81 
82 
83 }
View Code

 

posted @ 2020-10-24 22:05  canwinfor  阅读(193)  评论(0)    收藏  举报