T37302 P哥的桶

Posted yinwuxiao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了T37302 P哥的桶相关的知识,希望对你有一定的参考价值。

题解:

比较简单的一道题

线段树+线性基

显然离线处理出位置

然后线段树updata的时候暴力合并线性基

nlogn^3

一个常数优化就是线性基已满就直接返回这个线性基

还有个优化是用快速找到第一个1的函数

代码:

 

#include <bits/stdc++.h>
using namespace std;
#define rint register ll
#define IL inline
#define me(x) memset(x,0,sizeof(x))
#define rep(i,h,t) for (rint i=h;i<=t;i++)
#define dep(i,t,h) for (rint i=t;i>=h;i--)
ll n,m,num;
const ll N=12e4;
char ss[1<<24],*A=ss,*B=ss;
IL char gc()
{
  return A==B&&(B=(A=ss)+fread(ss,1,1<<24,stdin),A==B)?EOF:*A++; 
}
template<class T> void IL read(T &x)
{
  rint f=1,c; while (c=gc(),c<48||c>57) if (c==-) f=-1; x=(c^48);
  while (c=gc(),c>47&&c<58) x=(x<<3)+(x<<1)+(c^48); x*=f;
}
struct re{
  ll a,b,c;
}a[N];
ll cnt[N],sum[N];
vector<ll> ve;
struct sgt{
  #define mid ((h+t)/2)
  ll f[N*4][32];
  IL void cr(ll *c,ll k)
  {
      dep(i,31,1)
      {
        if (!k) return;
        if (k&(1<<(i-1)))
        {
          if (!c[i])
          {
            c[i]=k; return;
          } else k^=c[i];
        }
      }
  }
  struct re2{
    ll a[32];
    re2 ()
    {
      memset(a,0,sizeof(a));
    }
  };
  IL re2 hb(ll *x,ll *y)
  {
    ll cnt1=0,cnt2=0;
    rep(i,1,31) if (x[i]) cnt1++;
    rep(i,1,31) if (y[i]) cnt2++;
    re2 now;
    if(cnt1==31)
    {
      rep(i,1,31) now.a[i]=x[i]; 
      return(now);
    }
    if (cnt2==31)
    {
      rep(i,1,31) now.a[i]=y[i]; 
      return(now);
    }
    if (cnt1<cnt2)
    {
      rep(i,1,31) now.a[i]=y[i];
      rep(i,1,31)
        if (x[i]) cr(now.a,x[i]);
    } else
    {
      rep(i,1,31) now.a[i]=x[i];
      rep(i,1,31)
        if (y[i]) cr(now.a,y[i]);
    }
    return(now);
  }
  IL void updata(ll x)
  {
    re2 now=hb(f[x*2],f[x*2+1]);
    rep(i,1,31) f[x][i]=now.a[i];
  }
  void query(ll x,ll h,ll t,ll h1,ll t1)
  {
    if (h1<=h&&t<=t1)
    { 
      ve.push_back(x);
      return;
    }
    if (h1<=mid) query(x*2,h,mid,h1,t1);
    if (mid<t1) query(x*2+1,mid+1,t,h1,t1);
  }
  void change(ll x,ll h,ll t,ll pos,ll k)
  {
    if (h==t)
    {
      cr(f[x],k);
      return;
    }
    if (pos<=mid) change(x*2,h,mid,pos,k);
    else change(x*2+1,mid+1,t,pos,k);
    updata(x);
  }
  IL ll query2()
  {
    re2 now;
    for(ll i=0;i<ve.size();i++)
      now=hb(now.a,f[ve[i]]);
    ll ans=0;
    for(ll i=31;i>=1;i--)
      if (now.a[i]&&!(ans&(1<<(i-1)))) ans^=now.a[i];
    return ans;
  }
}S;
ll main()
{
  freopen("1.in","r",stdin);
  freopen("1.out","w",stdout);
  read(m); read(n);
  rep(i,1,m)
  {
    ll k,x,y;
    read(k); read(x); read(y);
    a[i].a=k; a[i].b=x; a[i].c=y;
    if (k==1) cnt[x]++;
  }
  rep(i,1,n) cnt[i]+=cnt[i-1];
  num=cnt[n];
  rep(i,1,m)
  {
    ll k=a[i].a,x=a[i].b,y=a[i].c;
    if (k==1)
    {
      sum[x]++;
      S.change(1,1,num,cnt[x-1]+sum[x],y);
    } else
    {
      ve.clear();
      if (cnt[x-1]+1<=cnt[y])
      {
        S.query(1,1,num,cnt[x-1]+1,cnt[y]);
        cout<<S.query2()<<endl;
      } else cout<<0<<endl;
    }
  }
  return 0; 
}

 

以上是关于T37302 P哥的桶的主要内容,如果未能解决你的问题,请参考以下文章

关于代码片段的时间复杂度

c#代码片段快速构建代码

Microsoft SQL Server 代码片段收集

js常用代码片段(更新中)

方便调试使用的代码片段

以下代码片段 C++ 的说明