zoukankan      html  css  js  c++  java
  • LOJ510 [LibreOJ NOI Round #1] 北校门外的回忆

    建立图论模型,(x)(x+operatorname{lowbit}(x)) 连边。当 (k) 为奇数时,因为 (k perp 2),所以 (x) 无论加多少次 (operatorname{lowbit}(x))(operatorname{lowbit}(x)) 的位数不会改变,得形成的图为若干条链,链相互不交。当 (k) 为偶数时,当最低位的数字含有的质因数 (2) 的个数不小于 (k) 的个数时,其和奇数的情况等价,会形成若干不交的链,也就是 (k) 为偶数时得到的图为若干相交的链。

    直接建图维护链的前缀异或和,复杂度无法接受,需要进一步优化。因为当最低位的数字中 (2) 的指数不小于 (k) 中的时,其就已经到了不交的链上,所以从任何一点,最多走 (log) 次就能到不交的链上。到链之前的信息暴力维护,链上的信息用动态开点线段树维护即可。

    现在的问题就只剩下走到一条不交的链上后,怎么知道其是哪一条链。可以在每一条链上选出一个代表点,其只有在最低位有值,每次到一条链上倍增跳到代表点,就能知道当前是哪一条链了。设 (f_{i,j}) 为最低位为 (i),将其除了最低位的高位减去 (2^j),会跳到哪里,处理出后就能倍增知道在哪一条链了。

    #include<bits/stdc++.h>
    #define maxn 200010
    #define maxm 6000010
    #define mid ((l+r)>>1)
    using namespace std;
    template<typename T> inline void read(T &x)
    {
        x=0;char c=getchar();bool flag=false;
        while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
        while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
        if(flag)x=-x;
    }
    int n,q,k,tot,all;
    int f[maxn][32],sum[maxm],ls[maxm],rs[maxm];
    map<int,int> val;
    map<pair<int,int>,int> rt;
    void modify(int l,int r,int pos,int v,int &cur)
    {
        if(!cur) cur=++tot;
        sum[cur]^=v;
        if(l==r) return;
        if(pos<=mid) modify(l,mid,pos,v,ls[cur]);
        else modify(mid+1,r,pos,v,rs[cur]);
    }
    int query(int l,int r,int pos,int cur)
    {
        if(!cur||l==r) return sum[cur];
        if(pos<=mid) return query(l,mid,pos,ls[cur]);
        else return sum[ls[cur]]^query(mid+1,r,pos,rs[cur]);
    }
    int get(int x)
    {
        while(!(x&1)) x>>=1;
        return x;
    }
    int find(int v)
    {
        int x=get(v%k);
        v/=k;
        for(int i=0;(1<<i)<=v;++i)
            if(v&(1<<i))
                x=f[x][i];
        return x;
    }
    void init()
    {
        int t=get(k);
        for(int i=1;i<t;i+=2) f[i][0]=get(i+t);
        for(int j=1;(1<<j)<=n;++j)
            for(int i=1;i<t;i+=2)
                f[i][j]=f[f[i][j-1]][j-1];
        all=(k&(-k))-1;
    }
    int main()
    {
        read(n),read(q),read(k),init();
        while(q--)
        {
            int opt,x,v,p=1,ans=0;
            read(opt),read(x);
            while(x%k==0) x/=k,p*=k;
            if(opt==1)
            {
                read(v);
                while(x*p<=n&&x&all)
                {
                    val[x*p]^=v,x+=x%k;
                    while(x%k==0) x/=k,p*=k;
                }
                if(x*p<=n) modify(1,n,x*p,v,rt[{find(x),p}]);
            }
            else
            {
                while(x)
                {
                    if(x&all) ans^=val[x*p];
                    else ans^=query(1,n,x*p,rt[{find(x),p}]);
                    if(!(x-=x%k)) break;
                    while(x%k==0) x/=k,p*=k;
                }
                printf("%d
    ",ans);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    mysql in 的另一种替换方法
    js 的一些总结
    医院收费系统 一点的简单总结
    物流系统
    mysqldump备份还原和mysqldump导入导出语句大全详解
    android 环境待建遇到的问题
    EXT CheckboxSelectionModel 多选效果
    Ext Grid动态生成Column的实现方式
    Javascript对象继承(原型继承法)
    ExtJS中grid的JsonStore、Ext.PagingToolbar带条件查询问题
  • 原文地址:https://www.cnblogs.com/lhm-/p/13907339.html
Copyright © 2011-2022 走看看