題解 CF703D Mishka and Interesting sum
阿新 • • 發佈:2021-06-12
這題非常類似 P1972 [SDOI2009]HH的項鍊,這是數顏色的題目的常見套路。
首先,出現偶數次的數的異或和 轉化為 所有數的異或和 與 所有不重複數的異或和 的異或和。
前者是字首和可以搞定的,後者就是區間數顏色的做法。先處理出每個點的顏色上一次出現位置 \(pre\)。離線詢問,按右端點排序,用樹狀陣列維護每個點。加入某個點時刪除它的 \(pre\),實現方法同 P1972 [SDOI2009]HH的項鍊。
#include <bits/stdc++.h> using namespace std; const int N=1000006; int n,m,tree[N]; int col[N],pre[N],s[N]; inline int lowbit(int x) { return x&(-x); } void add(int x,int k) { if (x==0) return; for (;x<=n;x+=lowbit(x)) tree[x]^=k; } int ask(int x) { int res=0; for (;x;x-=lowbit(x)) res^=tree[x]; return res; } struct ques { int l,r,id; }q[N]; inline int read() { int F=1,ANS=0; char C=getchar(); while (C<'0'||C>'9') { if (C=='-') F=-1; C=getchar(); } while (C>='0'&&C<='9') { ANS=ANS*10+C-'0'; C=getchar(); } return F*ANS; } bool cmp(ques x,ques y) { return x.r<y.r; } int ans[N]; map<int,int>a; int main() { n=read(); for (int i=1;i<=n;i++) { col[i]=read(); s[i]=s[i-1]^col[i]; pre[i]=a[col[i]]; a[col[i]]=i; } m=read(); for (int i=1;i<=m;i++) { q[i].id=i,q[i].l=read(),q[i].r=read(); } sort(q+1,q+m+1,cmp); int tot=0; for (int i=1;i<=m;i++) { while (tot<q[i].r) { tot++; add(tot,col[tot]),add(pre[tot],col[pre[tot]]); } ans[q[i].id]=ask(q[i].r)^ask(q[i].l-1)^s[q[i].r]^s[q[i].l-1]; } for (int i=1;i<=m;i++) printf("%d\n",ans[i]); return 0; }