静态区间数颜色问题
我知道这是很典的题,但是看提交记录发现我是今年 1 月做的,居然一点印象也没有。
看题解(洛谷第一篇)居然看懂了,比较开心。之前都是随便看看然后就开始贺题解,感觉思考的比较少,这次是看着推导过程写出来了。
思路:对于询问多个区间 [L,R] 中出现不同数字个数,当 R 相同时,如果区间出现了重复数字,那么我们只需要关心最右端的这个数字就可以了。换言之,重复出现的数字在左端将无任何贡献。例如 1 2 3 1 4,在询问 [1,4] 时,第一个 1 无任何贡献,并且当询问的 R 不断右移的过程中,第一个 1 都无任何意义,被第四位置的替代掉。
于是把询问离线下来,按照询问的右端点排序。
当出现一个数字时,如果这个数字曾经出现,则 insert(lst[pos[i]],-1)
,把这个数在上一个位置的标记清掉,insert(pos[i],1)
来更新这个数字的新位置。
用树状数组单点修改、区间查询,常数、空间都较小。用前缀和 query(R)-query(L-1)
把这一段的数字数出来。
#include<bits/stdc++.h>
const int N=1e6+10;
using namespace std;
int n,Q;
int a[N],t[N];
int lst[N],ans[N];
struct node{int L,R,id;}q[N];
bool cmp(node x,node y){
return x.R<y.R;
}
int lowbit(int x){
return x&(-x);
}
void insert(int x,int v){
while(x<=n){
t[x]+=v;
x+=lowbit(x);
}
}
int query(int x){
int res=0;
while(x){
res+=t[x];
x-=lowbit(x);
}
return res;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
scanf("%d",&Q);
for(int i=1;i<=Q;i++){
scanf("%d%d",&q[i].L,&q[i].R);
q[i].id=i;
}
sort(q+1,q+Q+1,cmp);
for(int i=1,top=1;i<=n;i++){
if(lst[a[i]]) insert(lst[a[i]],-1);
insert(i,1);
lst[a[i]]=i;
while(top<=Q&&q[top].R==i){
ans[q[top].id]=query(q[top].R)-query(q[top].L-1);
top++;
}
}
for(int i=1;i<=Q;i++) printf("%d\n",ans[i]);
return 0;
}
cf 703D Mishka and Interesting sum
求区间内出现次数为偶数次的数的异或值。
考虑:一个数异或两次为 0。
则所求答案为区间所有出现过的数与区间异或值的异或值。这样,所有出现过奇数次的数都会被异或掉(变成 0),出现过偶数次的数会被异或掉后再异或出来。即为答案。
维护情况和上一题一样。区间异或值直接用前缀和统计,出现过的数统计下来用树状数组维护。注意 a_i <=1e9 于是要离散化。
维护的过程中,在这个位置 insert;再将数字 x 上一次出现的位置 lst[x] 处变为 0,即再异或上一个自己就能实现。
Code
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int n,Q;
int a[N],s[N],b[N],tot;
map<int,int> vis;
int t[N],ans[N],lst[N];
struct node{int L,R,id;}q[N];
bool cmp(node x,node y){
return x.R<y.R;
}
int lowbit(int x){
return x&(-x);
}
void insert(int x,int v){
while(x<=n){
t[x]^=v;
x+=lowbit(x);
}
}
int query(int x){
int res=0;
while(x){
res^=t[x];
x-=lowbit(x);
}
return res;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
s[i]=s[i-1]^a[i];
if(!vis[a[i]]){
b[++tot]=a[i];
vis[a[i]]=tot;
a[i]=tot;
}
else a[i]=vis[a[i]];
}
scanf("%d",&Q);
for(int i=1;i<=Q;i++){
scanf("%d%d",&q[i].L,&q[i].R);
q[i].id=i;
}
sort(q+1,q+Q+1,cmp);
for(int i=1,top=1;i<=n;i++){
int t=a[i];
if(lst[t]) insert(lst[t],b[a[i]]);
insert(i,b[a[i]]);
lst[t]=i;
while(top<=Q&&q[top].R==i){
ans[q[top].id]=query(q[top].R)^query(q[top].L-1)^s[q[top].R]^s[q[top].L-1];
top++;
}
}
for(int i=1;i<=Q;i++) printf("%d\n",ans[i]);
return 0;
}
本文作者:Moyyer_suiy
本文链接:https://www.cnblogs.com/Moyyer-suiy/p/18500948
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
2023-10-24 鲜花 - 1