Tree ---樹鏈剖分之31個線段樹

Tree

一開始開了31個線段樹sum維護區間異或和,然後第五個點T了,之後又sum維護區間1的個數,然後第12個點T了,然後又把兩個循環合成了一個,然後提前算出來了一個數就A了,感覺時間卡的很離譜。 卡時間垃圾題。基本都是板子。

#include<iostream>
#include<cstdio>
using namespace std;
const int MAX_N=100100;
int head[MAX_N],ver[2*MAX_N],Next[2*MAX_N];
int tot,cnt;
void Add(int x,int y){
 ver[++tot]=y;Next[tot]=head[x];head[x]=tot;
}
int size[MAX_N],wson[MAX_N],dfn[MAX_N],deep[MAX_N],pre[MAX_N],top[MAX_N],fa[MAX_N];
struct node{
  int l,r,sum,lazy;
}a[32][MAX_N*4];
int b[MAX_N];
void update(int t,int k){
  a[t][k].sum=a[t][k<<1].sum+a[t][k<<1|1].sum;
}
void build(int t,int k,int l,int r){
  a[t][k].l=l;a[t][k].r=r;a[t][k].lazy=-1;
  if(l==r){
    a[t][k].sum=(b[pre[l]]>>t)&1;
    return;
  }
  int mid=(l+r)>>1;
  build(t,k<<1,l,mid);
  build(t,k<<1|1,mid+1,r);
  update(t,k);
}
void pushdown(int t,int k){
  if(a[t][k].lazy==-1)
  return;
  a[t][k<<1].lazy=a[t][k<<1|1].lazy=a[t][k].lazy;
  if(a[t][k].lazy==1){
   a[t][k<<1].sum=a[t][k<<1].r-a[t][k<<1].l+1;
   a[t][k<<1|1].sum=a[t][k<<1|1].r-a[t][k<<1|1].l+1;
 }
 else{
  a[t][k<<1].sum=0;
   a[t][k<<1|1].sum=0;
 }
  a[t][k].lazy=-1;
}
void changeS(int t,int k,int l,int r,int y){
  if(a[t][k].l>=l&&a[t][k].r<=r){
   if(y==0)
    a[t][k].sum=0;
    else
    a[t][k].sum=a[t][k].r-a[t][k].l+1;
    a[t][k].lazy=y;
    return;
  }
  pushdown(t,k);
  int mid=(a[t][k].l+a[t][k].r)>>1;
  if(l<=mid)
  changeS(t,k<<1,l,r,y);
  if(r>mid)
  changeS(t,k<<1|1,l,r,y);
  update(t,k);
}
int query(int t,int k,int l,int r){
  if(a[t][k].l>=l&&a[t][k].r<=r)
  return a[t][k].sum;
  pushdown(t,k);
  int mid=(a[t][k].l+a[t][k].r)>>1;
  int x=0;
  if(l<=mid)
  x+=query(t,k<<1,l,r);
  if(r>mid)
  x+=query(t,k<<1|1,l,r);
  return x;
}
void dfs1(int x,int fat){
    size[x]=1;
    for(int i=head[x];i;i=Next[i]){
        int y=ver[i];
        if(y==fat)
            continue;
        deep[y]=deep[x]+1;
        fa[y]=x;
        dfs1(y,x);
        size[x]+=size[y];
        if(size[wson[x]]<size[y])
            wson[x]=y;
    }
}
void dfs2(int x,int tp){
    dfn[x]=++cnt;
    pre[cnt]=x;
    top[x]=tp;
    if(wson[x])
        dfs2(wson[x],tp);
    for(int i=head[x];i;i=Next[i]){
        int y=ver[i];
        if(y!=wson[x]&&y!=fa[x])
            dfs2(y,y);
    }
}
void modify1(int x,int y,int d){//修改x到y路徑上的值
    while(top[x]!=top[y]){
        if(dfn[top[x]]<dfn[top[y]])
            swap(x,y);
        for(int i=0;i<31;i++){
         if((d>>i)&1)
         changeS(i,1,dfn[top[x]],dfn[x],1);
  }
        x=fa[top[x]];
    }
    if(deep[x]>deep[y])
        swap(x,y);
    for(int i=0;i<31;i++){
     if((d>>i)&1)
     changeS(i,1,dfn[x],dfn[y],1);
 }
}
void modify2(int x,int y,int d){//修改x到y路徑上的值
    while(top[x]!=top[y]){
        if(dfn[top[x]]<dfn[top[y]])
            swap(x,y);
        for(int i=0;i<31;i++){
         if(!((d>>i)&1))
         changeS(i,1,dfn[top[x]],dfn[x],0);
  }
        x=fa[top[x]];
    }
    if(deep[x]>deep[y])
        swap(x,y);
    for(int i=0;i<31;i++){
     if(!((d>>i)&1))
     changeS(i,1,dfn[x],dfn[y],0);
 }
}
int Qsum(int x,int y){
    int ans[35]={0};
    int ret=0;
    while(top[x]!=top[y]){
        if(dfn[top[x]]<dfn[top[y]])
            swap(x,y);
        for(int i=0;i<31;i++){
         ans[i]+=query(i,1,dfn[top[x]],dfn[x]);
  }
        x=fa[top[x]];
    }
    if(deep[x]>deep[y])
        swap(x,y);
    for(int i=0;i<31;i++){
     ans[i]+=query(i,1,dfn[x],dfn[y]);
     ret+=(ans[i]&1)<<i;
 }
    return ret;
}
int main(void){
 int n,m,i,op,s,t,x,y;
 scanf("%d%d",&n,&m);
 for(i=1;i<=n;i++){
  scanf("%d",&b[i]);
 }
 for(i=1;i<n;i++){
  scanf("%d%d",&x,&y);
  Add(x,y);
  Add(y,x);
 }
 deep[1]=1;
    dfs1(1,0);
    dfs2(1,1);
    for(i=0;i<31;i++)
    build(i,1,1,n);
    for(i=0;i<m;i++){
     scanf("%d%d%d",&op,&s,&t);
     if(op==1){
      modify1(1,s,t);
  }
  else if(op==2){
   modify2(1,s,t);
  }
  else if(op==3){
   int ans=Qsum(1,s);
   //cout<<ans<<"!!\n";
   ans^=t;
   if(ans)
   printf("YES\n");
   else
   printf("NO\n");
  }
 }
 return 0;
}
發佈了62 篇原創文章 · 獲贊 6 · 訪問量 1955
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章