牛客网暑期ACM多校训练营(第一场)J 题解

题目要我们查询两个区间的不同的数的个数。我们考虑一个区间内的做法。

我这里讲一下树状数组的做法

首先将原数组扩展为2倍长的,即 a[i+n] = a[i]

for (int i = 1; i <= n; i++) {
			scanf("%d", &a[i]);
			a[i + n] = a[i];}

对于查询a[1...l]和a[r..n]有多少种不同的数字可以转换为查询 a[r...l+n]有多少种不同的数字

	//区间处理,
		for (int i = 1; i <= q; i++) {
			scanf("%d %d", &f[i].x, &f[i].y);
			f[i].x += n;
			swap(f[i].x, f[i].y);
			f[i].pos = i;
		}

建立树状数组

	for (int i = 1; i <= 2 * n; i++) {
			if (fir[i]!=0) {
				add(i, 1);
			}
		}
/*void add(int i, int v) {
	while (x < MAXN) {
		c[x] += v;
		x += lowbit(x);
		int lowbit(int x) {
	return x & -x;
}*/


 输出

   int nextLIndex = 1;
        for (int i = 1; i <= 2 * n && nextLIndex <= q; ) 
        {
            if (i == f[nextLIndex].x)
            {
                // Query
                ans[f[nextLIndex].pos] = sum(f[nextLIndex].y) - sum(f[nextLIndex].x) + 1;
                nextLIndex++;
                //                printf("f[i].pos = %d ans = %d\n", f[i].pos, ans[f[i].pos]);
            }
            /*    int sum(int x) {
            int s = 0;
            while (x) {
               s += c[x];
              x -= lowbit(x);
             }
            return s;
             }
             int lowbit(int x) {
             return x & -x;
              }*/
            
            else {
                if (fir[i]) {
                    // Update,下一个更新为 1
                    fir[i] = 0;
                    add(i, -1);
                    fir[Next[i]] = 1;
                    add(Next[i], 1);
                    //                    display(n);
                }
                i++;
            }

        }

全部代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
const int maxn = 100005;
const int MAXN = 2 * maxn;
struct ss {
	int x, y, pos;
}f[maxn];
//loc[i] = i出现的位置
int loc[maxn], ans[maxn];
//Next[i] = i位置上的数下一个出现的位置
//fir[i] = i位置上的数是否为第一次出现
int a[MAXN], c[MAXN], Next[MAXN], fir[MAXN];

bool cmp(ss p, ss q) {
	return p.x < q.x;
}

int lowbit(int x) {
	return x & -x;
}
//a[i] += v
void add(int x, int v) {
	while (x < MAXN) {
		c[x] += v;
		x += lowbit(x);
	}
}
//a[1] + ... + a[x]
int sum(int x) {
	int s = 0;
	while (x) {
		s += c[x];
		x -= lowbit(x);
	}
	return s;
}

int main() {
	int n, q;
	while (~scanf("%d %d", &n, &q)) {

		//初始化变量,Fir初始化为1, 其余初始化为0
		memset(a, 0, sizeof(a));
		memset(loc, 0, sizeof(loc));
		memset(Next, 0, sizeof(Next));
		memset(ans, 0, sizeof(ans));
		memset(c, 0, sizeof(c));

		//		倍增数组,将对两个区间的查询转换为对单个区间的查询
		for (int i = 1; i <= n; i++) {
			//			cin>>a[i];
			scanf("%d", &a[i]);
			a[i + n] = a[i];
			fir[i] = 1;
			fir[i + n] = 1;
			//fir[i] = i位置上的数是否为第一次出现
		}

		//预处理Next、Fir数组
		for (int i = 2 * n; i > 0; i--) {
			fir[loc[a[i]]] = 0;
			Next[i] = loc[a[i]];
			loc[a[i]] = i;
			//loc[i] = i出现的位置
		}

		//预处理树状数组
		for (int i = 1; i <= 2 * n; i++) {
			if (fir[i]!=0) {
				add(i, 1);
			}
		}
		


		//区间处理,
		for (int i = 1; i <= q; i++) {
			scanf("%d %d", &f[i].x, &f[i].y);
			//			cin>>f[i].x>>f[i].y;
			f[i].x += n;
			swap(f[i].x, f[i].y);
			f[i].pos = i;
		}
	  /*	struct ss {
      int x, y, pos;
      }f[maxn];
      */
		//		区间排序
		sort(f + 1, f + q + 1, cmp);
         /*bool cmp(ss p, ss q) {
         	return p.x < q.x;
          }*/
		int nextLIndex = 1;
		for (int i = 1; i <= 2 * n && nextLIndex <= q; ) 
		{
			if (i == f[nextLIndex].x)
	    	{
				// Query
				ans[f[nextLIndex].pos] = sum(f[nextLIndex].y) - sum(f[nextLIndex].x) + 1;
				nextLIndex++;
				//				printf("f[i].pos = %d ans = %d\n", f[i].pos, ans[f[i].pos]);
			}
		    /*	int sum(int x) {
	        int s = 0;
        	while (x) {
	       	s += c[x];
		      x -= lowbit(x);
	         }
            return s;
             }
			 int lowbit(int x) {
	         return x & -x;
              }*/
            
			else {
				if (fir[i]) {
					// Update,下一个更新为 1
					fir[i] = 0;
					add(i, -1);
					fir[Next[i]] = 1;
					add(Next[i], 1);
					//					display(n);
				}
				i++;
			}

		}

		for (int i = 1; i <= q; i++) {
			printf("%d\n", ans[i]);
		}

	}

	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_42105529/article/details/81132044