SPOJ QTREE3 - Query on a tree again!

You are given a tree (an acyclic undirected connected graph) with N nodes. The tree nodes are numbered from 1 to N. In the start, the color of any node in the tree is white.

We will ask you to perfrom some instructions of the following form:

  • 0 i : change the color of the i-th node (from white to black, or from black to white);
    or
  • 1 v : ask for the id of the first black node on the path from node 1 to node v. if it doesn‘t exist, you may return -1 as its result.

Input

In the first line there are two integers N and Q.

In the next N-1 lines describe the edges in the tree: a line with two integers a b denotes an edge between a and b.

The next Q lines contain instructions "0 i" or "1 v" (1 ≤ i, v ≤ N).

Output

For each "1 v" operation, write one integer representing its result.

Example

Input:
9 8
1 2
1 3
2 4
2 9
5 9
7 9
8 9
6 8
1 3
0 8
1 6
1 7
0 2
1 9
0 2
1 9 

Output:
-1
8
-1
2
-1

Constraints & Limits

There are 12 real input files.

For 1/3 of the test cases, N=5000, Q=400000.

For 1/3 of the test cases, N=10000, Q=300000.

For 1/3 of the test cases, N=100000, Q=100000.

一棵树,点数<=100000,初始全是白点,支持两种操作: 
1.将某个点的颜色反色。 
2.询问某个点至根节点路径上第一个黑点是哪个。

树链剖分

注意到询问的链都是(1,v)

在线段树上维护区间内深度最浅的黑色点位置即可,注意线段树结点到原树的反向映射

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<queue>
  6 using namespace std;
  7 const int INF=1e9;
  8 const int mxn=100010;
  9 int read(){
 10     int x=0,f=1;char ch=getchar();
 11     while(ch<‘0‘ || ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
 12     while(ch>=‘0‘ && ch<=‘9‘){x=x*10-‘0‘+ch;ch=getchar();}
 13     return x*f;
 14 }
 15 struct edge{int v,nxt;}e[mxn<<1];
 16 int hd[mxn],mct=0;
 17 int n,q;
 18 void add_edge(int u,int v){
 19     e[++mct].v=v;e[mct].nxt=hd[u];hd[u]=mct;return;
 20 }
 21 struct node{
 22     int fa,son;
 23     int top,size;
 24     int w;
 25 }t[mxn];
 26 int sz=0;
 27 int dep[mxn];
 28 int id[mxn];
 29 void DFS1(int u,int fa){
 30     dep[u]=dep[fa]+1;
 31     t[u].size=1;
 32     for(int i=hd[u];i;i=e[i].nxt){
 33         int v=e[i].v;if(v==fa)continue;
 34         t[v].fa=u;
 35         DFS1(v,u);
 36         t[u].size+=t[v].size;
 37         if(t[v].size>t[t[u].son].size)
 38             t[u].son=v;
 39     }
 40     return;
 41 }
 42 void DFS2(int u,int top){
 43     t[u].w=++sz;t[u].top=top;
 44     id[sz]=u;
 45     if(t[u].son)DFS2(t[u].son,top);
 46     for(int i=hd[u];i;i=e[i].nxt){
 47         int v=e[i].v;
 48         if(v==t[u].fa || v==t[u].son)continue;
 49         DFS2(v,v);
 50     }
 51     return;
 52 }
 53 struct SGT{
 54     int ps;
 55     int c;
 56 }st[mxn<<2];
 57 void Build(int l,int r,int rt){
 58     st[rt].ps=INF;
 59     if(l==r)return;
 60     int mid=(l+r)>>1;
 61     Build(l,mid,rt<<1);Build(mid+1,r,rt<<1|1);
 62     return;
 63 }
 64 void update(int p,int l,int r,int rt){
 65     if(l==r){
 66         st[rt].c^=1;
 67         st[rt].ps=(st[rt].c)?l:INF;
 68         return;
 69     }
 70     int mid=(l+r)>>1;
 71     if(p<=mid)update(p,l,mid,rt<<1);
 72     else update(p,mid+1,r,rt<<1|1);
 73     st[rt].ps=min(st[rt<<1].ps,st[rt<<1|1].ps);
 74     return;
 75 }
 76 int query(int L,int R,int l,int r,int rt){
 77     if(L<=l && r<=R){return st[rt].ps;}
 78     int mid=(l+r)>>1;
 79     int res=INF;
 80     if(L<=mid)res=min(res,query(L,R,l,mid,rt<<1));
 81     if(R>mid && res>mid)res=min(res,query(L,R,mid+1,r,rt<<1|1));
 82     return res;
 83 }
 84 int Qt(int x,int y){
 85     int res=INF;
 86     while(t[x].top!=t[y].top){
 87         if(dep[t[x].top]<dep[t[y].top])swap(x,y);
 88         res=min(res,query(t[t[x].top].w,t[x].w,1,n,1));
 89         x=t[t[x].top].fa;
 90     }
 91     if(dep[x]>dep[y])swap(x,y);
 92     res=min(res,query(t[x].w,t[y].w,1,n,1));
 93     return res;
 94 }
 95 int main(){
 96     int i,j,u,v;
 97     n=read();q=read();
 98     for(i=1;i<n;i++){
 99         u=read();v=read();
100         add_edge(u,v);
101         add_edge(v,u);
102     }
103     DFS1(1,0);
104     DFS2(1,1);
105     Build(1,n,1);
106     while(q--){
107         u=read();v=read();
108         if(!u)
109             update(t[v].w,1,n,1);
110         else{
111             int ans=Qt(1,v);
112             if(ans>=INF){printf("-1\n");continue;}
113             ans=id[ans];
114             printf("%d\n",ans);
115         }
116     }
117     return 0;
118 }
时间: 2024-12-04 00:17:03

SPOJ QTREE3 - Query on a tree again!的相关文章

spoj 375. Query on a tree 【树链剖分--插点问线 】

题目:spoj 375. Query on a tree 题意:题意很清晰,就是给你一颗树,每两点之间有权值,然后改变一些权值,问一条路径上的最大值. 分析:入门题目,直接套树链模板 AC代码: #include <cstdio> #include <algorithm> #include <iostream> #include <string.h> using namespace std; const int N = 10010; #define Del(

SPOJ QTREE2 Query on a tree II

Query on a tree II Time Limit: 2000ms Memory Limit: 262144KB This problem will be judged on SPOJ. Original ID: QTREE264-bit integer IO format: %lld      Java class name: Main You are given a tree (an undirected acyclic connected graph) with N nodes,

SPOJ 375. Query on a tree (树链剖分)

Query on a tree Time Limit: 5000ms Memory Limit: 262144KB This problem will be judged on SPOJ. Original ID: QTREE64-bit integer IO format: %lld      Java class name: Main Prev Submit Status Statistics Discuss Next Font Size: + - Type:   None Graph Th

spoj 375 Query on a tree (树链剖分)

Query on a tree You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, 3...N-1. We will ask you to perfrom some instructions of the following form: CHANGE i ti : change the cost of the i-th edge to ti or Q

SPOJ QTREE Query on a tree ——树链剖分 线段树

[题目分析] 垃圾vjudge又挂了. 树链剖分裸题. 垃圾spoj,交了好几次,基本没改动却过了. [代码](自带常数,是别人的2倍左右) #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define maxn 20005 int T,n,fr[maxn],h[maxn],to[maxn],ne[maxn]

SPOJ QTREE - Query on a tree

Description You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, 3...N-1. We will ask you to perfrom some instructions of the following form: CHANGE i ti : change the cost of the i-th edge to tior QUERY

spoj 375 query on a tree LCT

这道题是树链剖分的裸题,正在学LCT,用LCT写了,发现LCT代码比树链剖分还短点(但我的LCT跑极限数据用的时间大概是kuangbin大神的树链剖分的1.6倍,所以在spoj上是850ms卡过的). 收获: 1.边转换成点(即若存在边(u,v),则新加一个点z代表边,将z连接u和v,z的点权就是(u,v)的边权,非边点的权设为-oo),然后对边权的统计就变成了对点权的统计(这是LCT中处理边信息的通法之一). 2.若要连接两个点u,v,先让它们分别称为根,然后将其中一个的path-parent

SPOJ QTREE Query on a tree --树链剖分

题意:给一棵树,每次更新某条边或者查询u->v路径上的边权最大值. 解法:做过上一题,这题就没太大问题了,以终点的标号作为边的标号,因为dfs只能给点分配位置,而一棵树每条树边的终点只有一个. 询问的时候,在从u找到v的过程中顺便查询到此为止的最大值即可. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath&

SPOJ 375 Query on a tree【树链剖分】

题目大意:给你一棵树,有两个操作1.修改一条边的值,2.询问从x到y路径上边的最大值 思路:如果树退化成一条链的话线段树就很明显了,然后这题就是套了个树连剖分,调了很久终于调出来第一个模板了 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #define maxn 100009 5 using namespace std; 6 int head[maxn],next[maxn*2],point[