zoukankan      html  css  js  c++  java
  • bzoj 4184 shallot——线段树分治+线性基

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4184

    本来想了可持久化trie,不过空间是 nlogn (出一个节点的时候把 tot 复原就能做到),时间是 nlog2n 的,不太可过。

    查了查发现就是线性基。因为新增一些数的话,线性基只会变大,所以可以很方便地栈序撤销。不过这样时间是不是还是 nlog2n ?

    现性基求最大值是看看异或上这个位上的数,答案能否变大。能的话就异或上。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<map>
    #include<vector>
    #define ls Ls[cr]
    #define rs Rs[cr]
    #define pb push_back
    using namespace std;
    int rdn()
    {
      int ret=0;bool fx=1;char ch=getchar();
      while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}
      while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
      return fx?ret:-ret;
    }
    const int N=5e5+5,M=N<<1,K=30;
    int n,tot,tp[N],Ls[M],Rs[M],b[K+5],bin[K+5];
    map<int,int> mp;
    vector<int> vt[M],cg[M];
    void build(int l,int r,int cr)
    {
      if(l==r)return; int mid=l+r>>1;
      ls=++tot; build(l,mid,ls);
      rs=++tot; build(mid+1,r,rs);
    }
    void ins(int l,int r,int cr,int L,int R,int k)
    {
      if(l>=L&&r<=R){vt[cr].pb(k);return;}
      int mid=l+r>>1;
      if(L<=mid)ins(l,mid,ls,L,R,k);
      if(mid<R)ins(mid+1,r,rs,L,R,k);
    }
    void ins(int k,int cr)
    {
      for(int t=K;t>=0;t--)
        {
          if(!(k&bin[t]))continue;
          if(b[t])k^=b[t];
          else{ b[t]=k; cg[cr].pb(t); return;}
        }
    }
    void dfs(int cr)
    {
      if(!cr)return;
      int sz=vt[cr].size();
      for(int i=0;i<sz;i++)
        ins(vt[cr][i],cr);
      if(!ls)
        {
          int ans=0;
          for(int t=K;t>=0;t--)
        if((ans^b[t])>ans)ans^=b[t];
          printf("%d
    ",ans);
        }
      else dfs(ls),dfs(rs);
      sz=cg[cr].size();
      for(int i=0;i<sz;i++)b[cg[cr][i]]=0;
    }
    int main()
    {
      bin[0]=1;for(int i=1;i<=K;i++)bin[i]=bin[i-1]<<1;
      n=rdn();
      tot=1;build(1,n,1);
      for(int i=1,d;i<=n;i++)
        {
          d=rdn();
          if(d>0) mp[d]=i,tp[i]=d;
          else ins(1,n,1,mp[-d],i-1,-d),tp[mp[-d]]=0;
        }
      for(int i=1;i<=n;i++)
        if(tp[i])ins(1,n,1,i,n,tp[i]);
      dfs(1); return 0;
    }
  • 相关阅读:
    FastDFS
    目前存在的问题
    MongoDB JAVA开发
    [Linux] Hexo 搭建个人博客
    新目标
    1年之后的拿高工资的资本,Java线程
    Oracle在VMware虚拟机安装的配置
    adb命令关闭打开手机wifi开关
    ADB命令横竖屏切换、关闭打开wifi
    使用adb命令提取安卓手机中安装的apk
  • 原文地址:https://www.cnblogs.com/Narh/p/10435041.html
Copyright © 2011-2022 走看看