2017.9.23 Count on a tree 思考记录
2017-09-23 17:41
232 查看
这个题就是把区间第k大搬到了树上、、
于是想到链剖、但链剖是要支持区间合并的,第k大显然不可以合并,那怎么办呢
所以就可以容斥,,把所有重链起点终点用两个rt截下来,再把每个+和每个-离散下来,然后由于主席树查找是logn的,离散的点最多有logn对,
所以复杂度是(2*nlog^2n) 可以卡过、
网上的题解是dfs序。。感觉dfs序好想比较神奇,,但已经不知道用多少链剖水过dfs了、
虽然很难写,但写完了比较好调,毕竟难点不在分类讨论、终于1A主席树+链剖辣
码:
于是想到链剖、但链剖是要支持区间合并的,第k大显然不可以合并,那怎么办呢
所以就可以容斥,,把所有重链起点终点用两个rt截下来,再把每个+和每个-离散下来,然后由于主席树查找是logn的,离散的点最多有logn对,
所以复杂度是(2*nlog^2n) 可以卡过、
网上的题解是dfs序。。感觉dfs序好想比较神奇,,但已经不知道用多少链剖水过dfs了、
虽然很难写,但写完了比较好调,毕竟难点不在分类讨论、终于1A主席树+链剖辣
码:
#include<iostream> #include<cstdio> #include<vector> #include<algorithm> #define N 100005 #include<map> using namespace std; int fu ,sz ,a,syg ,cnt,zj[100],sd[100],b,m,n,c,d ,siz[N*30],sta1[100][100],sta2[100][100],ch[N*30][2],dui ,ans,fd ,tot,top ,rt ,hson ; vector<int>v ; void dfs1(int o,int fa,int dis) { int i; fu[o]=fa; sz[o]=1; d[o]=dis; for(i=0;i<v[o].size();i++) { int nd=v[o][i]; if(nd==fa)continue; dfs1(nd,o,dis+1); if(sz[hson[o]]<sz[nd])hson[o]=nd; sz[o]+=sz[nd]; } } void up(int o) { siz[o]=siz[ch[o][0]]+siz[ch[o][1]]; } void jia(int o,int l,int r,int last) { if(l==r) { siz[o]=1; return ; } int mid=(l+r)>>1; if(c<=mid) { ch[o][0]=++tot; jia(ch[o][0],l,mid,ch[last][0]); ch[o][1]=ch[last][1]; } if(c>mid) { ch[o][1]=++tot; jia(ch[o][1],mid+1,r,ch[last][1]); ch[o][0]=ch[last][0]; } up(o); } int wr; void dfs2(int o,int tap) { int i; top[o]=tap; syg[o]=wr; rt[o]=++tot; //cout<<o<<" --> "<<rt[o]<<endl; c=dui[o]; jia(rt[o],1,n,rt[wr]); wr=o; if(hson[o]!=0)dfs2(hson[o],tap); for(i=0;i<v[o].size();i++) { int nd=v[o][i]; if(nd==fu[o]||nd==hson[o])continue; dfs2(nd,nd); } } void cha(int l,int r) { if(l==r) { ans=fd[l]; return; } int mid=(l+r)>>1; int i,lin=0; for(i=1;i<=cnt;i++) lin+=siz[ch[sta1[tot][i]][0]]; for(i=1;i<=cnt;i++) lin-=siz[ch[sta2[tot][i]][0]]; if(lin<c) { c-=lin; ++tot; for(i=1;i<=cnt;i++) sta1[tot][i]=ch[sta1[tot-1][i]][1],sta2[tot][i]=ch[sta2[tot-1][i]][1]; cha(mid+1,r); }else { ++tot; for(i=1;i<=cnt;i++) sta1[tot][i]=ch[sta1[tot-1][i]][0],sta2[tot][i]=ch[sta2[tot-1][i]][0]; cha(l,mid); } --tot; } void work(int x,int y) { ans=0;cnt=0; while(top[x]!=top[y]) { if(d[top[x]]<d[top[y]])swap(x,y); sd[++cnt]=syg[top[x]]; zj[cnt]=x; x=fu[top[x]]; } if(d[x]>d[y])swap(x,y); sd[++cnt]=syg[x]; zj[cnt]=y; // cout<<cnt; tot=0; ++tot; int i; for(i=1;i<=cnt;i++) sta1[tot][i]=rt[zj[i]],sta2[tot][i]=rt[sd[i]]; cha(1,n); } struct woc { int a,id; }s ; bool cmp(woc a,woc b) { return a.a<b.a; } int main() { int i,x,y,z; scanf("%d%d",&n,&m); for(i=1;i<=n;i++) { scanf("%d",&s[i].a); s[i].id=i; } sort(s+1,s+1+n,cmp); for(i=1;i<=n;i++) { dui[s[i].id]=i; fd[i]=s[i].a; } for(i=1;i<n;i++) { scanf("%d%d",&a,&b); v[a].push_back(b); v[b].push_back(a); } dfs1(1,0,1); dfs2(1,1); for(i=1;i<=m;i++) { scanf("%d%d%d",&x,&y,&c); x=x^ans; work(x,y); if(i!=m)printf("%d\n",ans); else printf("%d",ans); } }
相关文章推荐
- Count on a tree SPOJ - COT (LCA+主席树)
- bzoj 2588 Spoj 10628. Count on a tree
- [bzoj 2588] Spoj 10628. Count on a tree:函数式线段树
- [BZOJ2588][Spoj10628]Count on a tree(树上主席树)
- 【SPOJ】Count on a Tree Ⅱ (COT2)
- bzoj2588: Spoj 10628. Count on a tree 主席树+dfs序
- bzoj2588 Spoj 10628. Count on a tree
- [BZOJ2588][SPOJ10628]Count on a tree
- Count on a tree
- SPOJ COT2 Count on a tree II [树上莫队]
- bzoj2589: Spoj 10707 Count on a tree II
- BZOJ-2588-Count-on-a-tree-SPOJ10628-LCA+主席树
- [BZOJ 2588][SPOJ COT]Count On a Tree(DFS序主席树)
- SPOJ COT2 Count on a tree II [树上莫队]
- bzoj2588 Count on a tree(树上建主席树求路径第k大)
- [主席树] BZOJ 2588 Spoj 10628. Count on a tree
- BZOJ 2588 Count On a Tree 【LCA】【主席树】
- bzoj2588 Count on a tree dfs&主席树
- 2588: Spoj 10628. Count on a tree[可持久化线段树+倍增lca]
- spoj COT2 - Count on a tree II