心态崩了!树状数组+离线92pts,两个RE
查看原帖
心态崩了!树状数组+离线92pts,两个RE
1333709
itssapnap楼主2024/7/9 20:13

在参考了某评论区大佬之后,百思不得其解为什么大佬的没有RE但是我的RE了。

本ruogou代码如下:

#include<iostream>
#include<map>
#include<vector>
#include<algorithm>
#include<math.h>
using namespace std;

int ans[1000005];  //答案数组 
int arr[1000005];  //原始数据数组 
int tree[1000005];  
int vis[1000005];  //某一贝壳上一次出现的最右边位置 
int n,m;
struct ask{
	int l;//询问左端点 
	int r;//询问右端点 
	int id;//询问编号 
};
ask q[1000005];
 
bool cmp(ask a,ask b){
	if(a.r<=b.r)return true;
	else{
		return false;
	}
}
int lowbit(int i){
	return i&(-i);
}
int sum(int i){
	int ans=0;
	while(i>0){
		ans+=tree[i];
		i-=lowbit(i);
	}
	return ans;
}
void add(int v,int i){
	while(i<=n){
		tree[i]+=v;
		i+=lowbit(i);
	}
}

int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d",&arr[i]);
	}
	scanf("%d",&m);
	for(int i=1;i<=m;i++){
		int a,b,c;
		scanf("%d %d",&q[i].l,&q[i].r);
		q[i].id=i;
	}
	sort(q+1,q+1+m,cmp);//从1-m的排序 
	int pos=1;
	for(int i=1;i<=m;i++){
		for(int j=pos;j<=q[i].r;j++){
			int x=arr[j];
			if(vis[x]==0){
				add(1,j);
			}
			else{
				add(1,j);
				add(-1,vis[x]);
			}
			vis[x]=j;
		}
		pos=q[i].r+1;
		ans[q[i].id]=sum(q[i].r)-sum(q[i].l-1);
	}
	for(int i=1;i<=m;i++){
		printf("%d\n",ans[i]);
	}
	return 0; 
}

某大佬代码如下:

#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1000005;
int a[N]; // 原数组 
int c[N]; // 树状数组 
int p[N]; // p[i]表示i上一次出现的位置 
int ans[N]; // 存储答案 
int n, m; // 序列长度和询问次数 
struct ask // 存储每一次的询问 
{
	int l; // 询问中的左端点 
	int r; // 询问中的右端点 
	int id; // 这个询问的编号 
};
ask q[N]; // 存储询问 
bool cmp(ask x, ask y) // 把询问的右端点排序 
{
	return x.r < y.r; // 右端点小的放前面 
}
int lowbit(int x) // lowbit操作,表示x二进制分解下最低位的1 
{ 
	return x & (-x); // 利用补码性质实现lowbit操作
}
void update(int x, int y) // 单点增加 
{
	while(x <= n) // 边界限制 
	{
		c[x] += y; // 增加 
		x += lowbit(x); // 移动到下一个需要修改的点 
	}
}
int sum(int x) // 求前缀和 
{
	int ans = 0; // 答案 
	while(x >= 1) // 边界限制 
	{
		ans += c[x]; // 统计和 
		x -= lowbit(x); // 移动到下一个需要统计的点 
	}
	return ans; // 返回结果 
}
signed main()
{
	ios::sync_with_stdio(false);  // 加速读入 
	cin.tie(0), cout.tie(0);
	cin >> n; // 输入数据 
	for(int i=1;i<=n;i++) 
	{
		cin >> a[i]; // 输入数据 
	}
	cin >> m; // 输入数据 
	for(int i=1;i<=m;i++)
	{
		cin >> q[i].l >> q[i].r; // 输入数据,存储询问 
		q[i].id = i; // 存储当前询问的编号 
	}
	sort(q+1, q+1+m, cmp); // 把询问的右端点排序
	int nxt = 1; // 下一个需要处理的位置 
	for(int i=1;i<=m;i++) // 处理询问 
	{
		for(int j=nxt;j<=q[i].r;j++) 
		{
			if(p[a[j]] != 0) // 如果其前面出现过 
				update(p[a[j]], -1); // 将前面的标记-1清除 
			update(j, +1); // 把当前位置打标记 
			p[a[j]] = j; // 更新上一次出现的位置 
		}
		nxt = q[i].r+1; // 这一区间已经处理过了,下一次直接从后面处理 
		ans[q[i].id] = sum(q[i].r)-sum(q[i].l-1); // 计算该区间被标记没有重复的数 
	}
	for(int i=1;i<=m;i++) 
	{
		cout << ans[i] << '\n'; // 输出答案 
	}
	return 0; // 结束程序 
}

球球各位大佬帮帮aaaaa

2024/7/9 20:13
加载中...