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的)

  • 相关阅读:
    js中==与===区别
    Initialization failure 0x0000000c
    Spring通过@Value注解注入属性的几种方式
    java中读取配置文件中数据的具体方法
    spring整合hibernate
    url上参数解析笔记
    编号的生成(日期+序列号)
    application.xml & -servlet.xml
    webApplicationContext 与servletContext
    Http协议整理
  • 原文地址:https://www.cnblogs.com/yinwuxiao/p/9131329.html
Copyright © 2011-2022 走看看