zoukankan      html  css  js  c++  java
  • 北校门外的回忆

    这篇题解我真的是写了好多遍,每次快写好的时候就各种情况然后写的消失了

    题目链接

    这题要你求错误代码的结果,所以不是维护前缀异或和

    这题暴力时间上是可以过的,但是空间不行

    想到用动态开点线段树维护树状数组

    这下时间过不去了

    x+lowbit(x)相当于x的最低位*2,x向x+lowbit(x)连边

    在x不断向x+lowbit(x)跳的时候,lowbit(x)的非零位数字不断*2 mod k

    当k是奇数时,2与k互质,所以如果2a=2b(mod k),a=b(mod k)

    所以x -> x+lowbit(x)会形成若干不相交的链

    当k是偶数时,链会相交,就处理出不相交的链,用动态开点线段树维护

    对于不在链上的点就暴力跳到链上然后区间更新,在跳不超过log_2(k)∗log_k(n)=log_2(n)次后一定会跳到一条链上或跳出去。

    在链上的点就求出其所在的链和它在链中的位置,然后区间更新、

    lowbit(x)如果末尾有零,那x所在的链一定与模掉0之后的链是相似的,只要处理完后再把0乘回来即可

    #include<bits/stdc++.h>
    using namespace std;
    #define rep(i,j,k) for(int i=j;i<=k;++i)
    typedef long long ll;
    typedef double db;
    char cch;
    inline int rd(){
    	int x=0,fl=1;
    	cch=getchar();
    	while(cch>'9'||cch<'0'){
    		if(cch=='-') fl=-1;
    		cch=getchar();
    	}
    	while(cch>='0'&&cch<='9') x=(x<<3)+(x<<1)+cch-'0',cch=getchar();
    	return x*fl;
    }
    const int N=2e5+5;
    int st,dis,n,k,sz,pw[N],bz1[N][20],bz2[N][20],cnt[N],len[N],a[N];
    bool vis[N];
    struct tree{
    	int s,l,r;
    }tr[N*80];
    inline int lowbit(int x){//最低非零位上的数字 
    	while(x%k==0) x/=k;
    	return x%k; 
    }  
    inline int lowbitv(int x){//最低非零位的值 
    	int lg=1;
    	while(x%k==0) x/=k,lg*=k;
    	return x%k*lg;
    }
    inline void getst(int x){
    	int lg=1;
    	while(x%k==0) x/=k,lg*=k;//零是不影响的 
    	st=lowbit(x);//在哪条链 
    	int u=(x-st)/k;//要进几次位
        dis=u/cnt[st]*len[st]+1;//往回跳了多少个点
        u%=cnt[st];//剩下的不足一个环的 就倍增往回跳 
        for(int i=18;i>=0;i--) if(bz2[st][i]<=u) u-=bz2[st][i],dis+=(1<<i),st=bz1[st][i];
        st*=lg;
    }
    void init(){
    	int x,tot,w,to;
    	rep(i,1,k){
    		x=i;
    		while(x%2==0) ++pw[i],x/=2;
    	}
    	for(int i=1;i<k;++i) if(!vis[i]&&pw[i]>=pw[k]){
    		tot=0,w=0,a[++tot]=i,x=(i<<1)%k;
    		while(!vis[x]) 
    		vis[x]=1,a[++tot]=x,x=(x<<1)%k;//a存的是lowbit值形成的一个环
    		rep(j,1,tot) w+=(a[j]<<1)>=k;//注意是往回跳,所以 to存的是 a[(j-1+tot)%tot]
    		rep(j,1,tot) cnt[a[j]]=w,len[a[j]]=tot,to=a[(j-1+tot)%tot],bz1[a[j]][0]=to,bz2[a[j]][0]=(to<<1)/k;//len是这个环点长度,cnt是完整跳一个环会进多少位 
    		rep(h,1,18) rep(j,1,tot) bz1[a[j]][h]=bz1[bz1[a[j]][h-1]][h-1],bz2[a[j]][h]=bz2[bz1[a[j]][h-1]][h-1]+bz2[a[j]][h-1];//每个a[i]都更新,都作为链首
    	}//bz是往回跳会跳到哪个值的倍增数组,bz2是往回跳多少步会有多少进位的倍增数组 
    	 
    }
    void ins(int &d,int l,int r,int ql,int qr,int z){
        if (!d) d=++sz;
        if (ql<=l&&r<=qr){tr[d].s^=z;return;}
        int mid=(l+r)/2;
        if (ql<=mid) ins(tr[d].l,l,mid,ql,qr,z);
        if (qr>mid) ins(tr[d].r,mid+1,r,ql,qr,z);
    }
    int qry(int d,int l,int r,int x){ 
        if(l==r||!d) return tr[d].s;
        int mid=(l+r)/2;
        if(x<=mid) return qry(tr[d].l,l,mid,x)^tr[d].s;
        else return qry(tr[d].r,mid+1,r,x)^tr[d].s;
    }
    int main(){
    	n=rd();int ans,q=rd(),x,tmp,val,op,rt,root=0;k=rd();
    	init();
    	while(q--){
    		op=rd();
    		if(op==1){
    			x=rd(),val=rd();
    			while (x<=n&&pw[lowbit(x)]<pw[k]){//不在链上的点 
                    ins(root,1,n,x,x,val);//单点修改 
                    x+=lowbitv(x);
                }
                if(x>n) continue;//跳出n了
    			getst(x);//st是链首,dis是x在链中的位置 
    			rt=qry(root,1,n,st),/*查找st所在链对应的线段树的根*/tmp=rt,ins(rt,1,n,dis,n,val);
    			if(!tmp)ins(root,1,n,st,st,rt);//root是维护rt的,单点查询,这样写可以省一些代码 
    		}
    		else{
    			x=rd(),ans=0; 
    			while(x){
                    if (pw[lowbit(x)]<pw[k]) ans^=qry(root,1,n,x);//对于那些不在链上的点,root维护的就是点的值 
                    else{
                        getst(x);
                        int rt=qry(root,1,n,st);//因为x与x+lowbit(x)在同一条链,但是x与x+lowbit(x)-lowbit(x+lowbit(x))不一定在同一条链 
                        if(rt) ans^=qry(rt,1,n,dis);//所以单点查询 
                    }
                    x-=lowbitv(x);
                }
                printf("%d
    ",ans);
    		}
    	}
    } 
    
  • 相关阅读:
    如何解决WEB应用中文乱码问题
    js获取指定格式的时间字符串
    js 实现 Base64 编码的相互转换
    Sql Server 与 MySql 在使用 update inner join 时的区别
    VMware12创建新的虚拟机及设置硬件环境
    Sql Server 中使用日期遍历
    Linux 添加定时任务,crontab -e 命令与直接编辑 /etc/crontab 文件
    mysql 中 max_allowed_packet 查询和修改
    eclipse编译项目:Java @Override 注解报错的解决方法
    eclipse启动项目报错:java.lang.ClassNotFoundException: ContextLoaderListener
  • 原文地址:https://www.cnblogs.com/Doingdong/p/10710203.html
Copyright © 2011-2022 走看看