CF2153F
xujindong_ · · 题解
考虑这个神秘的限制是说不存在
我们可以考虑建出一个树形结构,将每种数以第一次出现为根连成一个菊花,数之间按嵌套关系连边。具体来说,维护一个栈,每次将当前位置连向栈顶,然后若它是第一次出现就入栈,若它是最后一次出现就出栈。这样的一棵树刻画了数的嵌套关系,其 DFS 序是原序列,每种相同的数构成菊花,且非第一次出现的数都是叶子。这也说明大小
现在考虑区间询问对应到 DFS 序。特判
单独算值等于 LCA 的点的奇偶性。对于
对于
瓶颈是树上
#include<bits/stdc++.h>
using namespace std;
int t,n,m,a[500005],visl[500005],visr[500005],st[500005],top,ft[500005][20],dep[500005],sz[500005],sib[500005],nxt[500005];
long long pre[500005],suf[500005],sum[500005],ans[500005];
bool o[500005],num[500005];
int main(){
ios::sync_with_stdio(0),cin.tie(0),cin>>t;
while(t--){
cin>>n>>m;
for(int i=1;i<=n;i++)cin>>a[i],visr[a[i]]=i,pre[i]=pre[i-1]+(o[a[i]]?-a[i]:a[i]),o[a[i]]^=1;
for(int i=1;i<=n;i++)o[i]=0;
for(int i=n;i>=1;i--)visl[a[i]]=i,suf[i]=suf[i+1]+(o[a[i]]?-a[i]:a[i]),o[a[i]]^=1;
for(int i=1;i<=n;i++){
ft[i][0]=st[top],dep[i]=dep[st[top]]+1,sz[i]=1;
for(int j=1;j<=__lg(dep[i]);j++)ft[i][j]=ft[ft[i][j-1]][j-1];
if(i==visl[a[i]])st[++top]=i;
if(i==visr[a[i]])top--;
}
for(int i=n;i>=1;i--){
int fa=ft[i][0];
if(a[i]!=a[fa])sum[i]+=o[a[i]]*a[i];
sz[fa]+=sz[i],sum[fa]+=sum[i],sum[i]+=sum[sib[fa]],num[i]=num[sib[fa]]^(a[i]==a[fa]),nxt[i]=sib[fa],sib[fa]=i;
}
for(int i=1,l,r;i<=m;i++){
cin>>l>>r,l=(l+ans[i-1]-1)%n+1,r=(r+ans[i-1]-1)%n+1;
if(l>r)swap(l,r);
if(l==r){
ans[i]=a[l];
continue;
}
int lca,u=l,v=r;
while(dep[u]>dep[v])u=ft[u][__lg(dep[u]-dep[v])];
while(dep[v]>dep[u])v=ft[v][__lg(dep[v]-dep[u])];
if(u==v)lca=u;
else{
for(int i=__lg(dep[u]);i>=0;i--)if(dep[u]>1<<i&&ft[u][i]!=ft[v][i])u=ft[u][i],v=ft[v][i];
lca=ft[u][0];
}
if(l==lca)ans[i]=pre[r]-pre[l-1];
else{
ans[i]=0;
bool type=0;
if(a[l]==a[lca])type^=1;
else ans[i]+=suf[l]-suf[u+sz[u]];
ans[i]+=sum[nxt[u]]-sum[v],type^=num[nxt[u]]^num[v];
if(a[r]==a[lca])type^=1;
else ans[i]+=pre[r]-pre[v-1];
if(type)ans[i]+=a[lca];
}
}
for(int i=1;i<=m;i++)cout<<ans[i]<<(i==m?'\n':' ');
for(int i=0;i<=n;i++)sum[i]=sib[i]=o[i]=num[i]=0;
top=0;
}
return 0;
}