【BZOJ】【2588】COT(Count On a Tree)
2015-03-16 11:05
405 查看
可持久化线段树
maya……树么……转化成序列……所以就写了个树链剖分……然后每个点保存的是从它到根的可持久化线段树。然后就像序列一样查询……注意是多个左端点和多个右端点,处理方法类似BZOJ 1901
然后rausen(Orz!!!)粗来跟我说:你直接减去lca和fa[lca]不就好啦~搞树剖还多一个log……
我恍然大悟!然后两个都交了一下,事实证明:我链剖写的还行,LCA写的太丑……速度反而是多一个log的链剖快QAQ(另:因为边少我就偷懒没写边表,直接vector水过)
链剖:
/************************************************************** Problem: 2588 User: Tunix Language: C++ Result: Accepted Time:4520 ms Memory:53024 kb ****************************************************************/ //BZOJ 2588 #include<vector> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define rep(i,n) for(int i=0;i<n;++i) #define F(i,j,n) for(int i=j;i<=n;++i) #define D(i,j,n) for(int i=j;i>=n;--i) #define pb push_back using namespace std; inline int getint(){ int v=0,sign=1; char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') sign=-1; ch=getchar();} while(isdigit(ch)) {v=v*10+ch-'0'; ch=getchar();} return v*sign; } const int N=1e5+10,INF=~0u>>2; /*******************template********************/ struct tree{ int cnt,l,r; }t[N*30]; int root ,cnt,num; int lc,rc,ln ,rn ; #define mid (l+r>>1) void update(int &o,int l,int r,int pos){ t[++cnt]=t[o]; o=cnt; t[o].cnt++; if (l==r) return; if (pos<=mid) update(t[o].l,l,mid,pos); else update(t[o].r,mid+1,r,pos); } int query_t(int rank){ int l=1,r=num; int tl=0,tr=0; while(l!=r){ tl=tr=0; F(i,1,lc) tl+=t[t[ln[i]].l].cnt; F(i,1,rc) tr+=t[t[rn[i]].l].cnt; if (tr-tl>=rank){ F(i,1,lc) ln[i]=t[ln[i]].l; F(i,1,rc) rn[i]=t[rn[i]].l; r=mid; }else{ F(i,1,lc) ln[i]=t[ln[i]].r; F(i,1,rc) rn[i]=t[rn[i]].r; l=mid+1; rank-=tr-tl; } } return l; } /*****************可持久化线段树 ***************/ vector<int>G ; int fa [18],dep ,a ,b ,n,m,lastans; void dfs(int x){ F(i,1,17) if (dep[x]>=(1<<i)) fa[x][i]=fa[fa[x][i-1]][i-1]; else break; root[x]=root[fa[x][0]]; update(root[x],1,num,a[x]); rep(i,G[x].size()){ int to=G[x][i]; if (to==fa[x][0]) continue; fa[to][0]=x; dep[to]=dep[x]+1; dfs(to); } } int LCA(int x,int y){ if (dep[x]<dep[y]) swap(x,y); int t=dep[x]-dep[y]; for(int i=0;(1<<i)<=t;i++) if(t&(1<<i)) x=fa[x][i]; D(i,17,0) if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; if (x==y) return x; return fa[x][0]; } void query(int x,int y,int k){ lc=rc=0; int lca=LCA(x,y); ln[++lc]=root[lca]; ln[++lc]=root[fa[lca][0]]; rn[++rc]=root[x]; rn[++rc]=root[y]; printf("%d",lastans=b[query_t(k)]); } /**********************LCA*********************/ int main(){ n=getint(); m=getint(); F(i,1,n) b[i]=a[i]=getint(); sort(b+1,b+n+1); num=unique(b+1,b+n+1)-b-1; F(i,1,n) a[i]=lower_bound(b+1,b+num+1,a[i])-b; int x,y,k; F(i,2,n){ x=getint(); y=getint(); G[x].pb(y); G[y].pb(x); } dfs(1); F(i,1,m){ x=lastans^getint(); y=getint(); k=getint(); query(x,y,k); if (i!=m) puts(""); } return 0; }
View Code
2588: Spoj 10628. Count on a tree
Time Limit: 12 Sec Memory Limit: 128 MBSubmit: 2581 Solved: 586
[Submit][Status][Discuss]
Description
给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权。其中lastans是上一个询问的答案,初始为0,即第一个询问的u是明文。Input
第一行两个整数N,M。第二行有N个整数,其中第i个整数表示点i的权值。
后面N-1行每行两个整数(x,y),表示点x到点y有一条边。
最后M行每行两个整数(u,v,k),表示一组询问。
Output
M行,表示每个询问的答案。Sample Input
8 5105 2 9 3 8 5 7 7
1 2
1 3
1 4
3 5
3 6
3 7
4 8
2 5 1
0 5 2
10 5 3
11 5 4
110 8 2
Sample Output
28
9
105
7
HINT
HINT:N,M<=100000
暴力自重。。。
Source
鸣谢seter[Submit][Status][Discuss]
相关文章推荐
- [BZOJ 2588][SPOJ COT]Count On a Tree(DFS序主席树)
- BZOJ 2588 Count on a tree (COT) 可持久化线段树
- BZOJ 2588 Count on a tree (COT) 是持久的段树
- [省选前题目整理][BZOJ 2588][SPOJ COT]Count On a Tree(DFS序主席树)
- [BZOJ2588][Spoj10628]Count on a tree(树上主席树)
- BZOJ BZOJ 2588: Spoj 10628. Count on a tree 树上主席树
- 【BZOJ2588】Count on a tree,主席树维护链+ST表求LCA
- 【bzoj2588】Count on a tree 主席树
- BZOJ 2588 Count on a tree 可持久化线段树+LCA
- BZOJ 2588: Spoj 10628. Count on a tree( LCA + 主席树 )
- bzoj 2588: Spoj 10628. Count on a tree【主席树+倍增】
- 【bzoj2588】Spoj 10628. Count on a tree LCA+主席树
- bzoj2588 Count on a tree
- bzoj2588 Spoj 10628. Count on a tree
- BZOJ 2588: Spoj 10628. Count on a tree
- BZOJ 2588 Count on a tree 主席树+倍增LCA
- [BZOJ2588] Count on a tree
- BZOJ2588 Spoj 10628. Count on a tree
- bzoj 2588 Spoj 10628. Count on a tree(主席树)
- 【BZOJ】2588: Spoj 10628. Count on a tree