在参考了某评论区大佬之后,百思不得其解为什么大佬的没有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