zoukankan      html  css  js  c++  java
  • bzoj2908

    题解:

    我的做法好像跟网上不太一样。

    首先分位讨论

    我的做法是先观察出了一个性质

    这个答案只跟最后一个0出现的位置有关(这个随便yy一下很容易出来因为运算有0则1)

    然后问题就变成了

    给出一棵树,支持单点修改,查询x向上第一个0的位置

    其实这个用lct维护比较方便。。而且这个复杂度是nlog^2的 我有空写下比较一下时间。。

    我写的是nlog^3的树剖维护。。注意到路径有向所以还要分情况分开写(第一次写)

    所以lct写起来应该非常简单。。。。除了updata改改其他就是模板了。。

    主要是这段时间在做线段树没想lct。。。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define IL inline
    #define rint register int
    #define mid ((h+t)/2)
    #define rep(i,h,t) for (rint i=h;i<=t;i++)
    #define dep(i,t,h) for (rint i=t;i>=h;i--)
    char ss[1<<27],*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 read(T &x)
    {
      rint f=1,c; while (c=gc(),c<48||c>57) if (c=='-') f=-1; x=c^48;
      while (c=gc(),47<c&&c<58) x=(x<<3)+(x<<1)+(c^48); x*=f;
    }
    void read2(char* x)
    {
      string s;
      char c;
      while (c=gc(),c!=' ') s+=c;
      strcpy(x,s.c_str());
    }
    char sr[1<<24],z[20]; int C=-1,Z;
    template <class T> void wer(T x)
    {
      if (x<0) sr[++C]='-',x=-x;
      while (z[++Z]=x%10+48,x/=10);
      while (sr[++C]=z[Z],--Z); sr[++C]='
    ';
    }
    IL int max(int x,int y)
    {
      if (x>y) return(x); else return(y);
    }
    IL int min(int x,int y)
    {
      if (x<y) return(x); else return(y);
    }
    IL void swap(int &x,int &y)
    {
      int tmp=x; x=y; y=tmp;
    }
    IL bool odd(int x)
    {
      if (x%2==1) return(1); else return(0);
    }
    const int N=1.1e5;
    char s[20];
    int l,head[N],v[N],fa[N],son[N],size[N],dfn[N],top[N],real2[N],dep[N],num,n,m,k;
    struct re{
      int a,b,c;
    }a[N*2];
    void arr(int x,int y)
    {
      a[++l].a=head[x];
      a[l].b=y;
      head[x]=l;
    }
    void dfs1(int x,int y)
    {
      fa[x]=y; size[x]=1; son[x]=0; dep[x]=dep[y]+1;
      int u=head[x];
      while (u)
      {
        int v=a[u].b;
        if (v!=y)
        { 
          dfs1(v,x);
          size[x]+=size[v];
          if (size[v]>size[son[x]]) son[x]=v;
        }
        u=a[u].a;
      }
    }
    void dfs2(int x,int y)
    {
      dfn[x]=++num; real2[num]=x;
      top[x]=y; if(!son[x]) return;
      dfs2(son[x],y);
      int u=head[x];
      while (u)
      {
        int v=a[u].b;
        if (v!=fa[x]&&v!=son[x]) dfs2(v,v);
        u=a[u].a;
      }
    }
    struct sgt{
      int f[N*4];
      sgt()
      {
        rep(i,0,N*4-1) f[i]=1; 
      }
      IL void updata(int x)
      {
        f[x]=f[x*2]&f[x*2+1];
      }
      void insert(int x,int h,int t,int pos,int k)
      {
        if (h==t)
        {
          f[x]=k; return;
        }
        if (pos<=mid) insert(x*2,h,mid,pos,k);
        else insert(x*2+1,mid+1,t,pos,k);
        updata(x);
      }
      vector<re> ve;
      void query5(int x,int h,int t,int h1,int t1)
      {
        if (h1<=h&&t<=t1)
        { 
          ve.push_back((re){x,h,t});
          return;
        }
        if (h1<=mid) query5(x*2,h,mid,h1,t1);
        if (mid<t1) query5(x*2+1,mid+1,t,h1,t1);
      }
      int query3(int x,int h,int t)
      {
        if (h==t) return(real2[h]);
        if (!f[x*2]) return(query3(x*2,h,mid));
        else return(query3(x*2+1,mid+1,t)); 
      }
      int query4(int x,int h,int t)
      {
        if (h==t) return(real2[h]);
        if (!f[x*2+1]) return(query4(x*2+1,mid+1,t));
        else return(query4(x*2,h,mid)); 
      }
      int query1(int x,int h,int t,int h1,int t1)
      {
        ve.clear();
        query5(x,h,t,h1,t1);
        dep(i,ve.size()-1,0)
          if (!f[ve[i].a]) return(query4(ve[i].a,ve[i].b,ve[i].c));
        return(-1);
      }
      int query2(int x,int h,int t,int h1,int t1)
      {
        ve.clear();
        query5(x,h,t,h1,t1);
        rep(i,0,ve.size()-1)
          if (!f[ve[i].a]) return(query3(ve[i].a,ve[i].b,ve[i].c));
        return(-1); 
      }
      int query(int x,int y)
      {
        int x1=x,x2,x3=y;
        vector<re> v1,v2;
        int f1=top[x],f2=top[y];
        while (f1!=f2)
        {
          if (dep[f1]<dep[f2])
          {
            v2.push_back((re){y,f2});
            y=fa[f2]; f2=top[y];
          } else
          {
            v1.push_back((re){x,f1});
            x=fa[f1]; f1=top[x];
          }
        }
        if (dep[x]<dep[y]) v2.push_back((re){y,x}),x2=x;
        else v1.push_back((re){x,y}),x2=y;
        rint ans;
     //   rep(i,0,(v1.size()-1))
        for (int i=0;i<v1.size();i++)
        {
          ans=query1(1,1,n,dfn[v1[i].b],dfn[v1[i].a]);
          if (ans!=-1) return(!odd(dep[x1]-dep[ans]));
        }
        for (int i=v2.size()-1;i>=0;i--)
        {
          ans=query2(1,1,n,dfn[v2[i].b],dfn[v2[i].a]);
          if (ans!=-1) return(!odd(-2*dep[x2]+dep[x1]+dep[ans]));
        }
        return(!odd(dep[x1]+dep[x3]-2*dep[x2]));
      }
    }sgt[33];
    int main()
    {
      freopen("1.in","r",stdin);
      freopen("1.out","w",stdout);
      read(n); read(m); read(k); 
      rep(i,1,n) read(v[i]);
      rep(i,1,n-1)
      {
        int x,y; read(x); read(y);
        arr(x,y); arr(y,x);
      }
      dfs1(1,0); dfs2(1,1);
      rep(i,0,k-1)
        rep(j,1,n)
          sgt[i].insert(1,1,n,dfn[j],(v[j]>>i)&1);
      rep(i,1,m)
      {
        int x,y;
        read2(s); read(x); read(y);
        if (s[0]=='Q')
        {
          ll ans=0;
          rep(j,0,k-1)
            ans+=1ll*sgt[j].query(y,x)*(1ll<<j);
          wer(ans);
        } else
        {
          rep(j,0,k-1)
            sgt[j].insert(1,1,n,dfn[x],(y>>j)&1);
        }
      }
      fwrite(sr,1,C+1,stdout);
      return 0; 
    }

     正解:

    其实正解很简单啊。。。

    首先分位讨论和我一样

    然后每次进去只有0/1两种

    所以直接上线段树就可以了

    但是这样也是nlog^3的(比我写的这个应该要简单啊,不用线段树二分了)

    我们考虑优化一下

    我们把进去的状态加一个 (1<<k)-1(这个还是非常巧妙的)

     我们需要进去的时候对(1<<k)-1 的值and一下 因为只有两个都为1之后才会为1

    而对于0的值我们需要取反再and

    这样就做到了nlog^2(这个一定是可以碾压lct的)

  • 相关阅读:
    leetcode 13. Roman to Integer
    python 判断是否为有效域名
    leetcode 169. Majority Element
    leetcode 733. Flood Fill
    最大信息系数——检测变量之间非线性相关性
    leetcode 453. Minimum Moves to Equal Array Elements
    leetcode 492. Construct the Rectangle
    leetcode 598. Range Addition II
    leetcode 349. Intersection of Two Arrays
    leetcode 171. Excel Sheet Column Number
  • 原文地址:https://www.cnblogs.com/yinwuxiao/p/9131329.html
Copyright © 2011-2022 走看看