hdu1762 树的上的查询


2015-10-07 20:44:42


题意问的是给了一颗树,然后又1000000次查询u,v,问不在树路径上的点的编号最小值,以1为根 建这颗树,然后在同一棵子树中的点子让就输出1 否则我们记录每个点从离1最近的那个点也就是1的孩子,到该点所经过的最小值,以及在他父亲到1的孩子,这段间和他不在同一条叉到上的最小值,还有就是他子树的最小值,然后遍历一遍,每次查询的时候搞一下就好了

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string.h>
using namespace std;
const int maxn=1000005;
template <class T>
inline bool rd(T &ret) {
    char c; int sgn;
    if (c = getchar(), c == EOF) return 0;
    while (c != '-' && (c<'0' || c>'9')) c = getchar();
    sgn = (c == '-') ? -1 : 1;
    ret = (c == '-') ? 0 : (c - '0');
    while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
    ret *= sgn;
    return 1;
}
template <class T>
inline void pt(T x) {
    if (x <0) {
        putchar('-');
        x = -x;
    }
    if (x>9) pt(x / 10);
    putchar(x % 10 + '0');
}
int fa[maxn],H[maxn],to[maxn*2],nx[maxn*2],numofE;
int upMIN[maxn],downMIN[maxn][2],other[maxn];
int belong[maxn];

void init(int N){
  numofE=0;
  memset(H,0,sizeof(H));
}
void add(int u,int v)
{
    numofE++;
    to[numofE]=v;
    nx[numofE]=H[u];
    H[u]=numofE;
}
int Q[maxn];
void cmp(int O,int a){
   if(a<downMIN[O][0]){
      downMIN[O][1]=downMIN[O][0];
      downMIN[O][0]=a;
   }else if(a<downMIN[O][1]){
      downMIN[O][1]=a;
   }
}
void searchroot(int cur)
{
     int rear=0;
     Q[rear++]=cur;
     fa[cur]=1;
     belong[cur]=cur;
     upMIN[cur]=cur;
     for(int i=0; i<rear; i++)
     {
         int x=Q[i];
         other[x]=downMIN[x][0]=downMIN[x][1]=maxn;
         for(int j=H[x]; j; j=nx[j])
         {
             int too=to[j];
             if(too==fa[x])continue;
             Q[rear++]=too;
             fa[too]=x;
             upMIN[too]=min(too,upMIN[x]);
             belong[too]=cur;
         }
     }
     for(int i=rear-1; i>=0; i--)
     {
         int x=Q[i];
         for(int j=H[x]; j; j=nx[j])
         {
             int too=to[j];
             if(too==fa[x])continue;
             int a=min(too,downMIN[too][0]);
             cmp(x,a);
         }
     }

     for(int i=1; i<rear; i++){
         int x=Q[i];
         int a=min(x,downMIN[x][0]);
         int f=fa[x];
         if(a!=downMIN[f][0]){
            other[x]=min(other[f],downMIN[f][0]);
         }else{
            other[x]=min(other[f],downMIN[f][1]);
         }
     }
}
int A[4],B[5];
void jud(int a)
{
    A[3]=a;
    for(int i=2; i>=0; i--)
        if(A[i]>A[i+1])swap(A[i],A[i+1]);
        else break;
}
void solve1(int a,int b)
{
    for(int i=0; i<3; i++)
    if(A[i]!=a&&A[i]!=b){
        B[0]=A[i];return ;
    }
}
int jud2()
{
    int v=B[0];
    for(int i=1;i<5;i++)
        v=min(B[i],v);
    return v;
}

int main()
{
    int N,q;
    downMIN[1][0]=downMIN[1][1]=other[1]=upMIN[1]=maxn;
    while(scanf("%d%d",&N,&q)==2)
    {
       init(N);
       for(int i=1; i<N; i++)
       {
           int a,b;
           rd(a);rd(b);

           add(a,b);add(b,a);
       }
       A[0]=A[1]=A[2]=maxn;
       for(int i=H[1]; i; i=nx[i])
        {
            searchroot(to[i]);
            jud(min(to[i],downMIN[to[i]][0]));
        }
        int d=0;
       for(int i=0; i<q; i++)
       {
           int a,b;
           rd(a);rd(b);
           a^=d;b^=d;
           if(a==1&&b==1){
             d=2;
             puts("2");continue;
           }
           if(belong[a]==belong[b]){
               d=1;
               puts("1");continue;
           }
           if(a==1||b==1){
              a=max(a,b);b=max(a,b);
           }
           solve1(upMIN[a],upMIN[b]);
           B[1]=other[a];B[2]=other[b];
           B[3]=downMIN[a][0];B[4]=downMIN[b][0];
           d=jud2();
           printf("%d
",d);
        }
    }

    return 0;
}
View Code
原文地址:https://www.cnblogs.com/Opaser/p/4859448.html