[ABC347E] Set Add Query题解

思路

通过读题发现,每个数变化当且仅当这个数在集合内。所以不妨设它被添加进来的时间点为 Li,它被删除的时间点为 Ri,所以它被增加的数量就是这段时间内集合数量之和。所以用一个变量 cnt 模拟当前集合内有多少个数,前缀和维护即可。具体实现参见代码。

代码

#include<bits/stdc++.h>
using namespace std;
#define int long long
int a[200010];
int sum[200010];
unordered_map<int,int> mp;// map判重
int ans[200010];
int p[200010];// 每个数出现的位置, 相当于 L_i
signed main() {
int n,m;
cin>>n>>m;
for(int i=1;i<=m;i++) cin>>a[i];
int cnt=0;
for(int i=1;i<=n;i++) p[i]=1;
for(int i=1;i<=m;i++) {
if(mp[a[i]]==1) {// 重复了
ans[a[i]]+=sum[i-1]-sum[p[a[i]]-1];
cnt--;
mp[a[i]]=0;
p[a[i]]=i;
}
else { // 没有重复
cnt++;
mp[a[i]]=1;
p[a[i]]=i;
}
sum[i]=cnt;
sum[i]=sum[i-1]+sum[i];
//cout<<sum[i]<<" ";
}
//cout<<sum[4]<<"\n";
for(int j=1;j<=n;j++) {
int i=m+1;
a[i]=j;
if(mp[a[i]]==1) {
ans[a[i]]+=sum[m]-sum[p[a[i]]-1];
//cout<<m<<" "<<p[i]-1<<"\n";
cnt--;
mp[a[i]]=0;
}
else {
cnt++;
mp[a[i]]=1;
}
}
for(int i=1;i<=n;i++) cout<<ans[i]<<" ";
return 0;
}

本文作者:merlinkkk

本文链接:https://www.cnblogs.com/merlinkkk/p/18306127

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   merlinkkk  阅读(19)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
展开