hdu5390 tree

  先求出dfs序,然后建立线段树,线段树每个节点套一个set。

  修改操作只需要改被子树区间完全覆盖的线段树节点,将其节点中set的原来的值删除,加入新值。

  询问操作查询单点到根的所有节点上的set中与查询值异或起来最大的那个。

  查询set中的数与x异或的最大值,可以从高位到低位枚举二进制位,根据x的二进制位,查询一些set中数值的存在情况,例如加入x的二进制第y位为1,那么如果set中存在第y位为0的数字,明显可以使得答案更大。下面代码中这段的代码类似于二分。

  时间复杂度O(nlogn^3)

  

  代码

  1 #include
  2 #include<set>
  3 #include
  4 #include
  5 #define N 500010
  6 using namespace std;
  7 int n,m,i,a,b,typ;
  8 int dp,p[N],pre[N],tt[N];
  9 int tot,L[N],R[N],l[N],r[N],v[N],stack[N],deep,flag;
 10 multiset<int> Set[N];
 11 void link(int x,int y)
 12 {
 13     dp++;pre[dp]=p[x];p[x]=dp;tt[dp]=y;
 14 }
 15 void dfs()
 16 {
 17     int i;
 18     while (deep)
 19     {
 20         if (L[stack[deep]]==0)
 21         {
 22             tot++;
 23             L[stack[deep]]=tot;
 24         }
 25         if (p[stack[deep]])
 26         {
 27             i=p[stack[deep]];
 28             deep++;stack[deep]=tt[i];
 29             p[stack[deep-1]]=pre[i];
 30         }
 31         else
 32         {
 33             R[stack[deep]]=tot;
 34             deep--;
 35         }
 36     }
 37 }
 38 void build(int x,int a,int b)
 39 {
 40     int m;
 41     l[x]=a;r[x]=b;
 42     Set[x].clear();
 43     Set[x].insert(-1);
 44     Set[x].insert(1<<30);
 45     if (b-a>1)
 46     {
 47         m=(a+b)>>1;
 48         build(2*x,a,m);
 49         build(2*x+1,m,b);
 50     }
 51 }
 52 void change(int x,int a,int b,int c,int d)
 53 {
 54     if ((a<=l[x])&&(r[x]<=b))
 55     {
 56         Set[x].insert(d);
 57         if (flag)
 58         Set[x].erase(c);
 59         return;
 60     }
 61     int m=(l[x]+r[x])>>1;
 62     if (a2*x,a,b,c,d);
 63     if (m2*x+1,a,b,c,d);
 64 }
 65 int Q(int x,int y)
 66 {
 67     int l,r,m,p,q;
 68     if (Set[x].size()==2) return 0;
 69     l=0;r=(1<<30)-1;
 70     while (l!=r)
 71     {
 72         m=(l+r)>>1;
 73         multiset<int>::iterator it=Set[x].upper_bound(m);
 74         p=*it;
 75         q=*(--it);
 76         if (p>r)
 77             r=m;
 78         else
 79         if (q<l)
 80             l=m+1;
 81         else
 82         {
 83             if ((l^y)>((m+1)^y))
 84             r=m;
 85             else
 86             l=m+1;
 87         }
 88     }
 89     return l^y;
 90 }
 91 int query(int x,int a,int b,int c)
 92 {
 93     int ans=Q(x,c);
 94     if ((a<=l[x])&&(r[x]<=b))
 95     return ans;
 96     int m=(l[x]+r[x])>>1;
 97     if (a2*x,a,b,c));
 98     if (m2*x+1,a,b,c));
 99     return ans;
100 }
101 int main()
102 {
103     int test;
104     scanf("%d",&test);
105     while (test--)
106     {
107     scanf("%d%d",&n,&m);
108     dp=0;
109     for (i=1;i<=n;i++)
110     {
111         L[i]=0;
112         p[i]=0;
113     }
114     for (i=2;i<=n;i++)
115     {
116         scanf("%d",&a);
117         link(a,i);
118     }
119     tot=0;
120     deep=1;stack[1]=1;
121     dfs();
122 
123     build(1,0,n);
124     flag=0;
125     for (i=1;i<=n;i++)
126     {
127         scanf("%d",&v[i]);
128         change(1,L[i]-1,R[i],0,v[i]);
129     }
130     flag=1;
131     for (i=1;i<=m;i++)
132     {
133         scanf("%d",&typ);
134         if (typ==0)
135         {
136             scanf("%d%d",&a,&b);
137             change(1,L[a]-1,R[a],v[a],b);
138             v[a]=b;
139         }
140         else
141         {
142             scanf("%d",&a);
143             printf("%d\n",query(1,L[a]-1,L[a],v[a]));
144         }
145     }
146     }
147 }

 

转载于:https://www.cnblogs.com/fzmh/p/4731579.html

你可能感兴趣的:(hdu5390 tree)