【填坑向】spoj COT/bzoj2588 Count on a tree

这题是学主席树的时候就想写的,,,

但是当时没写(懒)

现在来填坑

= =日常调半天lca(考虑以后背板)

主席树还是蛮好写的,但是代码出现重复,不太好,导致调试的时候心里没底(虽然事实证明主席树部分没出问题)

 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 struct lis{    int x,id;} li[100001];
 5 struct nod{    int num,ls,rs;} t[8000001];
 6 int n,m,x,y,z,sum=0,N=0,lastans=0;
 7 int to[200001],nex[200001],list[200001];
 8 int a[100001],h[100001],fir[100001],root[100001],f[100001],pos[100001];
 9 int log[200001],near[200001],rmq[20][200001];
10 bool operator<(lis a,lis b){    return a.x<b.x;}
11 void add(int x,int y,int z){    to[z]=y;nex[z]=fir[x];fir[x]=z;}
12 inline int lca(int x,int y){    if(x>y)    swap(x,y);
13     return (h[rmq[log[y-x+1]][x]]<h[rmq[log[y-x+1]][y-near[y-x+1]+1]])?
14     rmq[log[y-x+1]][x]:rmq[log[y-x+1]][y-near[y-x+1]+1];}
15 void build(int now,int fa)
16 {
17     f[now]=fa;root[now]=++sum;
18     int com=root[fa],cha=root[now],l=1,r=n;
19     while(l<r)
20         if(a[now]>(l+r)/2)
21             l=(l+r)/2+1,t[cha]=(nod){t[com].num+1,t[com].ls,++sum},cha=sum,com=t[com].rs;
22         else
23             r=(l+r)/2,t[cha]=(nod){t[com].num+1,++sum,t[com].rs},cha=sum,com=t[com].ls;
24     list[++N]=now;pos[now]=N;t[cha]=(nod){t[com].num+1,0,0};h[now]=h[fa]+1;
25     for(int i=fir[now];i;i=nex[i])
26     if(to[i]!=fa)
27         build(to[i],now),list[++N]=now;
28 }
29 void que(int x,int y,int z)
30 {
31     int l=1,r=n,lc=lca(pos[x],pos[y]),lcc=f[lc];
32     x=root[x],y=root[y],lc=root[lc],lcc=root[lcc];
33     while(l<r)
34         if(t[t[x].ls].num+t[t[y].ls].num-t[t[lc].ls].num-t[t[lcc].ls].num<z)
35             l=(l+r)/2+1,z-=t[t[x].ls].num+t[t[y].ls].num-t[t[lc].ls].num-t[t[lcc].ls].num,
36             x=t[x].rs,y=t[y].rs,lc=t[lc].rs,lcc=t[lcc].rs;
37         else
38             r=(l+r)/2,x=t[x].ls,y=t[y].ls,lc=t[lc].ls,lcc=t[lcc].ls;
39     lastans=li[l].x;
40 }
41 int main()
42 {
43     scanf("%d%d",&n,&m);
44     for(int i=1;i<=n;i++)
45         scanf("%d",&li[i].x),li[i].id=i;
46     sort(li+1,li+n+1);
47     for(int i=1;i<=n;i++)
48         a[li[i].id]=i;
49     for(int i=1;i<n;i++)
50         scanf("%d%d",&x,&y),add(x,y,i),add(y,x,i+n);
51     build(1,0);
52     for(int i=1;i<=N;i++)
53         rmq[0][i]=list[i];
54     for(int i=1,j=0,k=1;i<=N;log[i]=j,near[i]=k,i++)
55         if(i>k*2)    j++,k*=2;
56     for(int i=1,k=2;k<=N;i++,k*=2)
57         for(int j=1;j<=N-k+1;j++)
58             rmq[i][j]=(h[rmq[i-1][j]]<h[rmq[i-1][j+k/2]])?rmq[i-1][j]:rmq[i-1][j+k/2];
59     for(int i=1;i<=m;i++)
60         scanf("%d%d%d",&x,&y,&z),que(/*lastans^*/x,y,z),printf(i<m?"%d\n":"%d",lastans);
61     return 0;
62 } //lastans^加上以后就是强在,bzoj上的题;不加就是不强在,spoj上的题

 

顺便吐槽:spoj上内存限制1.5G实在太6,,,

导致我乱开数组,交bzoj的时候MLE了很多发

posted @ 2016-08-09 08:25  汪立超  阅读(139)  评论(0编辑  收藏  举报