听上去很高端,实则就是将多次询问读入后,再统一进行处理;而不是读一个解决一个。
洛谷p1972 HH的项链
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<string> 5 #include<cmath> 6 #include<cstdio> 7 #define ll long long 8 using namespace std; 9 const int maxn = 1e6 + 10; 10 int n, m; 11 int t[maxn]; 12 int a[maxn]; 13 int b[maxn]; 14 int vis[maxn]; 15 16 struct que 17 { 18 int x,y; 19 int id; 20 int res; 21 }query[maxn]; 22 23 bool cmp(const que &a, const que &b) 24 { 25 if(a.y == b.y) return a.x < b.x; 26 return a.y < b.y; 27 } 28 29 bool cmp2(const que &a, const que &b) 30 { 31 return a.id < b.id; 32 } 33 int lowbit(int x) 34 { 35 return x & -x; 36 } 37 void add(int x, int val) 38 { 39 for(int i = x ; i <= n ; i += lowbit(i)){ 40 t[i] += val; 41 } 42 } 43 int getsum(int x) 44 { 45 int sum = 0; 46 for(int i = x ; i > 0 ; i -= lowbit(i)){ 47 sum += t[i]; 48 } 49 return sum; 50 } 51 52 void solve() 53 { 54 scanf("%d",&m); 55 int x, y, res; 56 for(int i = 1 ; i <= m ; i++){ 57 scanf("%d%d",&query[i].x,&query[i].y); 58 query[i].id = i; 59 } 60 sort(query + 1, query + m + 1, cmp); 61 62 int r = 1; 63 for(int i = 1 ; i <= m ; i++){ 64 while(r <= query[i].y){ 65 int j = r; 66 if(vis[a[j]]){ 67 add(vis[a[j]], -1); 68 } 69 vis[a[j]] = j; 70 add(j, 1); 71 r++; 72 } 73 74 if(query[i].x == 1){ 75 query[i].res = getsum(query[i].y); 76 }else{ 77 query[i].res = getsum(query[i].y) - getsum(query[i].x - 1); 78 } 79 } 80 81 82 sort(query + 1, query + m + 1, cmp2); 83 for(int i = 1 ; i <= m ; i++){ 84 printf("%d ",query[i].res); 85 } 86 } 87 88 int main(){ 89 scanf("%d",&n); 90 for(int i = 1 ; i <= n ; i++){ 91 scanf("%d",&a[i]); 92 b[i] = a[i]; 93 } 94 sort(b + 1, b + n + 1); 95 m = unique(b + 1, b + n + 1) - b - 1; 96 for(int i = 1 ; i <= n ; i++){ 97 a[i] = lower_bound(b + 1, b + n + 1, a[i]) - b; 98 } 99 solve(); 100 101 return 0; 102 }
按照询问的右端点进行排序。
每个元素是否出现仅与其最右侧出现的位置是否位于查询区间内有关。
树状数组 + 离线