题目链接:https://loj.ac/p/510
给出一个代码
其中lowbit(x) lowbit(x) 表示x x 在K K 进制下最低非零位的值。
现在给出n , q , K n , q , K ,q q 次调用a d d ( x , v ) a d d ( x , v ) 或者q u e r y ( x ) q u e r y ( x ) 。
要求输出每次q u e r y ( x ) q u e r y ( x ) 调用的值。
1 ≤ n ≤ 10 9 , 2 ≤ q , K ≤ 2 × 10 5 1 ≤ n ≤ 10 9 , 2 ≤ q , K ≤ 2 × 10 5
注意到询问的时候我们是可以一位一位的做的,主要是修改的时候。
我们先默认最低非零位就是个位,那么相当于每次x = x + x % K x = x + x % K 直到x | K x | K ,如果只考虑个位的情况,也可以视为每次x = 2 x % K x = 2 x % K 。
首先每个数只有两种到达它的情况,一个是x 2 x 2 ,另一个是x + K 2 x + K 2 ,那么如果K K 是奇数的话,这两个中恰好有一个是整数,也就是每个数字的入边都是1 1 ,出边也是1 1 ,所以最终图肯定会形成若干个环。
那么考虑K K 不是奇数的情况,如果x x 的2 2 质因子个数不少于K K 的,那么它们则可以表示为x 2 p x 2 p 和K 2 p K 2 p ,这样的话K K 又是奇数了,也会构成环。
否则x x 一直乘二直到质因子个数不少于K K ,也就是说这种情况走不超过log K log K 步就一定能到达一个环或者0 0 。
那么我们就是先分位计算,最低位不在环上就暴力跳,在环上就考虑维护。
现在主要是环上怎么维护的问题,同一个最低位上,对于一个修改x y x y (个位是y y ,剩下的位是x x ),会影响一个询问x ′ y ′ x ′ y ′ 的条件。
我们需要找到一个不关于这些点的个位的条件,那么我们就考虑对于每个环定义一个点作为环头,然后所有的操作询问都移动到环头上搞。
然后我们把每个修改拆成修改位置到环头一段和从环头开始不停绕环的一段,
那么第一个的一个限制是询问位置要在它后面并且它们都反着退到环头后值相等,可以用线段树维护位置关系。
第二个先把询问倒着移动到环头,那么限制就是它们对于环上进位次数和 的余数相等并且询问的值大于修改的值,可以用权值线段树维护。
时间复杂度:O ( K log 2 n ) O ( K log 2 n )
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#define mp(x,y) make_pair(x,y)
using namespace std;
const int N=2e5 +10 ,M=N<<7 ;
int n,q,K,cnt,lg[N],id[N],sum[N],noe[N],dis[N],len[N];
map<pair<int ,int > ,int >rt[40 ],Rt[40 ];
map<int ,int > g;
struct SegTree {
int cnt,w[M],ls[M],rs[M];
void Change (int &x,int L,int R,int pos,int val) {
if (pos<L||pos>R)return ;
if (!x)x=++cnt;w[x]^=val;
if (L==R)return ;int mid=(L+R)>>1 ;
if (pos<=mid)Change (ls[x],L,mid,pos,val);
else Change (rs[x],mid+1 ,R,pos,val);
return ;
}
int Ask (int x,int L,int R,int l,int r) {
r=min (r,R);l=max (l,L);
if (l>r||!w[x])return 0 ;
if (L==l&&R==r)return w[x];
int mid=(L+R)>>1 ;
if (r<=mid)return Ask (ls[x],L,mid,l,r);
if (l>mid)return Ask (rs[x],mid+1 ,R,l,r);
return Ask (ls[x],L,mid,l,mid)^Ask (rs[x],mid+1 ,R,mid+1 ,r);
}
}T;
void dfs (int x,int pos,int one,int fr) {
if (id[x]){sum[fr]=one;return ;}
noe[x]=one;id[x]=fr;dis[x]=pos;len[fr]++;
dfs (x*2 %K,pos+1 ,one+(x*2 >=K),fr);
return ;
}
int main ()
{
scanf ("%d%d%d" ,&n,&q,&K);
for (int i=1 ;i<=K;i++)
if (i%2 ==0 )lg[i]=lg[i/2 ]+1 ;
for (int i=1 ;i<K;i++)
if (lg[i]>=lg[K]&&!id[i])
++cnt,dfs (i,0 ,0 ,cnt);
while (q--){
int op;scanf ("%d" ,&op);
if (op==1 ){
int x,w,i=0 ,pw=1 ;
scanf ("%d%d" ,&x,&w);
while (x*pw<=n){
int p=x%K,y=x/K;
while (p&&x*pw<=n){
if (lg[p]>=lg[K]){
T.Change (rt[i][mp (id[p],y-noe[p])],0 ,len[id[p]]-1 ,dis[p],w);
T.Change (Rt[i][mp (id[p],(y-noe[p]+sum[id[p]])%sum[id[p]])],0 ,n/pw/K,y+sum[id[p]]-noe[p],w);
x=0 ;break ;
}
else g[x*pw]^=w,x+=x%K,p=x%K,y=x/K;
}
if (!x||x*pw>n)break ;
x=x/K;pw=pw*K;i++;
}
}
else {
int x;scanf ("%d" ,&x);
int i=0 ,pw=1 ,ans=0 ;
while (x){
int p=x%K,y=x/K;
if (p!=0 ){
if (lg[p]>=lg[K]){
ans^=T.Ask (rt[i][mp (id[p],y-noe[p])],0 ,len[id[p]]-1 ,0 ,dis[p]);
ans^=T.Ask (Rt[i][mp (id[p],(y-noe[p]+sum[id[p]])%sum[id[p]])],0 ,n/pw/K,0 ,y-noe[p]);
}
else ans^=g[x*pw];
}
x/=K;i++;pw=pw*K;
}
printf ("%d\n" ,ans);
}
}
return 0 ;
}
__EOF__
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
2021-07-14 jzoj7175-[2021.07.14NOI模拟]种蘑菇(mushroom)【莫比乌斯反演,树形dp】
2021-07-14 P7726-天体探测仪(Astral Detector)【构造】