BSOJ3194:黑白树 树链剖分 TLE90分

来源:互联网 发布:数值模拟软件 编辑:程序博客网 时间:2024/04/30 05:31
这个应该能交过SPOJ上的题,没试过

3194 -- 【Astar 2008】黑白树
Description
在图论中,包含n个结点(结点编号为1~n)、n-1条边的无向连通图被称为树。在树中,任意一对结点间的简单路径总是惟一的。你拥有一棵白色的树——所有节点都是白色的。接下来,你需要处理c条指令:

修改指令(0 v):改变一个给定结点的颜色(白变黑,黑变白)
查询指令(1 v):询问从结点1到一个给定结点所经过的第一个黑色结点编号(假设沿着简单路径走)。 

注意,在查询指令中,必须从结点1而不是结点v出发。如果结点1本身就是黑色,查询指令应该返回1。 
Input
第一行包含两个正整数n,c,即结点数和指令条数。
以下n-1行,每行两个正整数(ui,vi)(1≤ui<vi≤n),表示结点ui到vi之间有一条无向边.
以下c行,每行两个整数(c,v)。当c=0时表示修改指令,其中v代表被修改的结点编号;c=1时表示查询指令。
你的程序需要输出结点1到结点v之间路径的第一个黑色结点编号。
在第一条指令执行前,所有结点都是白色的。
Output
对于每个查询操作(c=1的操作),输出一行,包含一个整数,即第一个黑色结点的编号。如果不存在黑色结点,输出-1。
Sample 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
Sample Output
-1
8
-1
2
-1
Hint
【数据范围】
0≤N≤1000000,0≤C≤1000000

草稿如下。
图片 
直接插入tid值


#include<iostream>#include<cstdio>#include<cstring>#define L(x) (x<<1)#define R(x) (x<<1|1)#define INF 0x7fffffffusing namespace std;int fa[3000005]={0},top[3000005]={0},son[3000005]={0},size[3000005]={0};int tid[3000005]={0},dep[3000005]={0};int rank[3000005]={0};struct SegmentTree{int l,r,p;}tree[3000005];int n,m;inline void swap(int &a,int &b){a^=b;b^=a;a^=b;}inline int getint(){int bj=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')bj=-1;ch=getchar();}int ret=0;while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();return ret*bj;}struct Edge{int to,next;}w[3000005]={0};int tim=0;int minn=INF;int cnt=0;int h[3000005]={0};inline void add(int x,int y){cnt++;w[cnt].to=y;w[cnt].next=h[x];h[x]=cnt;}void DFS1(int x,int f,int d){dep[x]=d;fa[x]=f;size[x]=1;for(int i=h[x];i;i=w[i].next){int to=w[i].to;if(to!=f){DFS1(to,x,d+1);size[x]+=size[to];if(son[x]==0||size[son[x]]<size[to])son[x]=to;}}}void DFS2(int x,int tp){top[x]=tp;tid[x]=++tim;rank[tim]=x;if(son[x]==0)return;DFS2(son[x],tp);for(int i=h[x];i;i=w[i].next){int to=w[i].to;if(to!=son[x]&&to!=fa[x])DFS2(to,to);}}inline void Pushup(int x){    tree[x].p=min(tree[L(x)].p,tree[R(x)].p);    return;}void build(int l,int r,int root){tree[root].l=l;tree[root].r=r;    tree[root].p=INF;if(l==r)return;int mid=(l+r)>>1;build(l,mid,L(root));build(mid+1,r,R(root));Pushup(root);//}inline void change(int x,int root){if(tree[root].l==tree[root].r)//{if(tree[root].p==INF)tree[root].p=tree[root].l;else tree[root].p=INF;return;}int mid=(tree[root].l+tree[root].r)>>1;if(x<=mid)change(x,L(root));else change(x,R(root));Pushup(root);}inline void get(int l,int r,int root)//{if(l<=tree[root].l&&tree[root].r<=r){minn=min(minn,tree[root].p);return;}int mid=(tree[root].l+tree[root].r)>>1;if(l<=mid)get(l,r,L(root));if(r>mid) get(l,r,R(root));}inline void mi(int x,int y){int t1=top[x],t2=top[y];while(t1!=t2){if(dep[t1]<dep[t2]){swap(t1,t2);swap(x,y);}get(tid[t1],tid[x],1);x=fa[t1];t1=top[x];}if(dep[x]>dep[y])swap(x,y);get(tid[x],tid[y],1);if(minn==INF)printf("-1\n");else printf("%d\n",rank[minn]);}int main(){    n=getint();m=getint();     for(int i=1;i<n;i++)     {     int a,b;     a=getint();b=getint();     add(a,b);     add(b,a);}DFS1(1,0,1);DFS2(1,1);build(1,n,1);while(m--){int cmd,a;cmd=getint();a=getint();if(cmd==0)change(tid[a],1);else {minn=INF;mi(1,a);}}return 0;} 


inline优化+getint优化+哲学swap,仍然在第二组随机100W数据下超时
图片 


0 0