zoukankan      html  css  js  c++  java
  • spoj 2798 Query on a tree again! 树链剖分

    题意:给定一棵树,每个节点颜色是黑色或者是白色。初始时,全白。

    定义两种操作

    0 i 改变第i个节点

    1 v 询问从1到v的路径上,第一个黑节点

      1 #include<iostream>
    2 #include<cstring>
    3 #include<cmath>
    4 #include<cstdio>
    5 using namespace std;
    6 #define MAXN 100010
    7 #define INF 987654321
    8 struct node
    9 {
    10 int r;
    11 node *next;
    12 };
    13 struct tree_node
    14 {
    15 int left,right;
    16 int num;
    17 };
    18 node *graph[MAXN];
    19 node memo[MAXN*2];
    20 tree_node tree[4*MAXN];
    21 int d[MAXN],father[MAXN],line[MAXN],son[MAXN],top[MAXN],mark[MAXN],home[MAXN];
    22 int n,m,label,color[MAXN],etop;
    23 void add(int x,int y)
    24 {
    25 node *p=&memo[etop++];
    26 p->r=y; p->next=graph[x]; graph[x]=p;
    27 p=&memo[etop++];
    28 p->r=x; p->next=graph[y]; graph[y]=p;
    29 }
    30 int dfs1(int i,int deep,int fa)
    31 {
    32 d[i]=deep; father[i]=fa;
    33 int size=1,maxsize=0,temp;
    34 for(node *p=graph[i];p;p=p->next)
    35 if(p->r!=father[i])
    36 {
    37 temp=dfs1(p->r,deep+1,i);
    38 if(temp>maxsize)
    39 {
    40 maxsize=temp; son[i]=p->r;
    41 }
    42 size+=temp;
    43 }
    44 return size;
    45 }
    46 void dfs2(int x,int y)
    47 {
    48 mark[x]=++label; top[x]=y;
    49 home[label]=x;
    50 if(son[x]==-1) return ;
    51 dfs2(son[x],y);
    52 for(node *p=graph[x];p;p=p->next)
    53 if(p->r!=father[x]&&p->r!=son[x]) dfs2(p->r,p->r);
    54 }
    55 void build_tree(int i)
    56 {
    57 tree[i].num=INF;
    58 if(tree[i].left==tree[i].right) return ;
    59 int mid=(tree[i].left+tree[i].right)/2;
    60 tree[2*i].left=tree[i].left; tree[2*i].right=mid;
    61 tree[2*i+1].left=mid+1; tree[2*i+1].right=tree[i].right;
    62 build_tree(2*i); build_tree(2*i+1);
    63 }
    64 void change(int i,int x)
    65 {
    66 if(tree[i].left==tree[i].right)
    67 {
    68 if(tree[i].num==INF) tree[i].num=tree[i].left;
    69 else tree[i].num=INF;
    70 return ;
    71 }
    72 int mid=(tree[i].left+tree[i].right)/2;
    73 if(x<=mid) change(2*i,x);
    74 else change(2*i+1,x);
    75 tree[i].num=min(tree[2*i].num,tree[2*i+1].num);
    76 }
    77 int search(int i,int x,int y)
    78 {
    79 if(tree[i].left==x&&tree[i].right==y)
    80 return tree[i].num;
    81 int mid=(tree[i].left+tree[i].right)/2;
    82 if(y<=mid) return search(2*i,x,y);
    83 else if(x>mid) return search(2*i+1,x,y);
    84 else return min(search(2*i,x,mid),search(2*i+1,mid+1,y));
    85 }
    86 void build()
    87 {
    88 dfs1(1,1,-1);
    89 dfs2(1,1);
    90 tree[1].left=1; tree[1].right=n;
    91 build_tree(1);
    92 }
    93
    94
    95 void solve()
    96 {
    97 int c,x,nx,ans;
    98 for(int i=1;i<=m;i++)
    99 {
    100 scanf("%d%d",&c,&x);
    101 if(c==0) change(1,mark[x]);
    102 else
    103 {
    104 for(ans=INF;x!=-1;x=father[nx])
    105 {
    106 nx=top[x];
    107 ans=min(ans,search(1,mark[nx],mark[x]));
    108 }
    109 if(ans==INF) printf("-1\n");
    110 else printf("%d\n",home[ans]);
    111 }
    112 }
    113 }
    114 int main()
    115 {
    116 scanf("%d%d",&n,&m);
    117 int x,y;
    118 int i;
    119 memset(graph,0,sizeof(graph));
    120 memset(son,0xff,sizeof(son));
    121 etop=label=0;
    122 for(i=1;i<n;i++)
    123 {
    124 scanf("%d%d",&x,&y);
    125 add(x,y);
    126 }
    127 build();
    128 solve();
    129 return 0;
    130 }



  • 相关阅读:
    Meta http-equiv属性详解(转)
    meta
    meta viewport 详解
    jquery 常用函数
    jquery 设置css样式
    jquery 常用函数集锦
    DATEDIFF 和 DATEADD
    C# 二进制图片串互转
    C# 二进制字符串互转
    重集合中找出最相近的一个数字
  • 原文地址:https://www.cnblogs.com/myoi/p/2379518.html
Copyright © 2011-2022 走看看