一道题14

$n \leq 200000$的树,有点权,给$m \leq 200000$个询问,每次问$x,k$,$x$向上走$k$步到的点的子树内和$x$同层的,除了$x$以外的点的点权众数。

询问挂点上,全图搜一次。每层开个线段树,合并的时候保留孩子里最长的一个,其他的暴力并过来。

复杂度:看起来是启发式合并但是只有一个$log$的。因为合并操作只会进行最多$n-1$次(菊花树)。

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<stdlib.h>
  4 //#include<math.h>
  5 //#include<queue>
  6 #include<vector>
  7 #include<algorithm>
  8 //#include<iostream>
  9 //#include<assert.h>
 10 using namespace std;
 11 
 12 int n,m;
 13 #define maxn 200011
 14 
 15 struct Edge{int to,next;}edge[maxn<<1]; int first[maxn],le=2;
 16 void in(int x,int y) {Edge &e=edge[le]; e.to=y; e.next=first[x]; first[x]=le++;}
 17 
 18 struct Ques{int id,d,x,next;}ques[maxn]; int fques[maxn],lq=2;
 19 void inque(int x,int id,int d,int y)
 20 {Ques &e=ques[lq]; e.id=id; e.d=d; e.x=y; e.next=fques[x]; fques[x]=lq++;}
 21 
 22 struct SMT
 23 {
 24     struct Node
 25     {
 26         int ls,rs;
 27         int Max,cnt;
 28     }a[maxn*18];
 29     int size,n;
 30     void clear(int m) {n=m; size=0;}
 31     void up(int x)
 32     {
 33         Node &b=a[x];
 34         if (a[b.ls].cnt>a[b.rs].cnt) {b.Max=a[b.ls].Max; b.cnt=a[b.ls].cnt;}
 35         else {b.Max=a[b.rs].Max; b.cnt=a[b.rs].cnt;}
 36     }
 37     void modify(int &x,int L,int R,int v,int type)
 38     {
 39         (!x && (x=++size));
 40         if (L==R) {a[x].cnt+=type; a[x].ls=a[x].rs=0; if (a[x].cnt) a[x].Max=v; else a[x].Max=0; return;}
 41         int mid=(L+R)>>1;
 42         if (v<=mid) modify(a[x].ls,L,mid,v,type); else modify(a[x].rs,mid+1,R,v,type);
 43         up(x);
 44     }
 45     void modify(int &rt,int v,int type) {modify(rt,1,n,v,type);}
 46     int combine(int x,int y,int L,int R)
 47     {
 48         if (!x || !y) return x^y;
 49         if (L==R) {a[x].cnt+=a[y].cnt; if (a[x].cnt) a[x].Max=L; else a[x].Max=0; return x;}
 50         int mid=(L+R)>>1;
 51         a[x].ls=combine(a[x].ls,a[y].ls,L,mid);
 52         a[x].rs=combine(a[x].rs,a[y].rs,mid+1,R);
 53         up(x); return x;
 54     }
 55     int combine(int x,int y) {return combine(x,y,1,n);}
 56 }t;
 57 
 58 int fa[20][maxn],dep[maxn];
 59 void predfs(int x,int f)
 60 {
 61     dep[x]=dep[f]+1; fa[0][x]=f;
 62     for (int i=first[x];i;i=edge[i].next)
 63     {
 64         Edge &e=edge[i]; if (e.to==f) continue;
 65         predfs(e.to,x);
 66     }
 67 }
 68 void makefa()
 69 {
 70     for (int j=1;j<=18;j++)
 71         for (int i=1;i<=n;i++)
 72             fa[j][i]=fa[j-1][fa[j-1][i]];
 73 }
 74 int jump(int x,int k)
 75 {
 76     for (int j=0;k;k>>=1,j++) if (k&1) x=fa[j][x];
 77     return x;
 78 }
 79 
 80 int val[maxn],lisa[maxn],li=0;
 81 
 82 vector<int> v[maxn]; int len=0;
 83 int root[maxn],vid[maxn],ans[maxn];
 84 void combine(int x,int y)
 85 {
 86     int i=v[x].size()-1,j=v[y].size()-1;
 87     while (j>=0)
 88     {
 89         v[x][i]=t.combine(v[x][i],v[y][j]);
 90         i--; j--;
 91     }
 92 }
 93 void dfs(int x)
 94 {
 95     int Max=0;
 96     for (int i=first[x];i;i=edge[i].next)
 97     {
 98         Edge &e=edge[i]; if (e.to==fa[0][x]) continue;
 99         dfs(e.to); if (v[vid[e.to]].size()>v[vid[Max]].size()) Max=e.to;
100     }
101     t.modify(root[x],val[x],1);
102     if (Max)
103     {
104         vid[x]=vid[Max];
105         for (int i=first[x];i;i=edge[i].next)
106         {
107             Edge &e=edge[i]; if (e.to==fa[0][x] || e.to==Max) continue;
108             combine(vid[Max],vid[e.to]);
109         }
110         v[vid[x]].push_back(root[x]);
111     }
112     else {len++; vid[x]=len; v[len].push_back(root[x]);}
113     
114     for (int i=fques[x];i;i=ques[i].next)
115     {
116         Ques &e=ques[i];
117         int p=v[vid[x]].size()-e.d-1,now=v[vid[x]][p];
118         t.modify(now,val[e.x],-1);
119         if (t.a[now].Max==0) ans[e.id]=-1;
120         else ans[e.id]=lisa[t.a[now].Max];
121         t.modify(now,val[e.x],1);
122     }
123 }
124 
125 int qread()
126 {
127     char c; int s=0; while ((c=getchar())<'0' || c>'9');
128     do s=s*10+c-'0'; while ((c=getchar())>='0' && c<='9'); return s;
129 }
130 int main()
131 {
132     n=qread(); int root;
133     for (int i=1,x;i<=n;i++) {x=qread(); if (x) in(x,i); else root=i;}
134     predfs(root,0); makefa();
135     
136     for (int i=1;i<=n;i++) val[i]=qread(),lisa[i]=val[i];
137     li=n; sort(lisa+1,lisa+1+n); li=unique(lisa+1,lisa+1+n)-lisa-1;
138     for (int i=1;i<=n;i++) val[i]=lower_bound(lisa+1,lisa+1+li,val[i])-lisa;
139     t.clear(li);
140     
141     m=qread();
142     for (int i=1,x,y;i<=m;i++)
143     {
144         x=qread(); y=qread();
145         int z=jump(x,y);
146         if (z) inque(z,i,y,x); else ans[i]=-1;
147     }
148     dfs(root);
149     for (int i=1;i<=m;i++) printf(ans[i]==-1?"ZYPRESSEN\n":"%d\n",ans[i]);
150     return 0;
151 }
View Code

 

posted @ 2018-04-11 08:59  Blue233333  阅读(156)  评论(0编辑  收藏  举报