zoukankan      html  css  js  c++  java
  • 一道题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
    ":"%d
    ",ans[i]);
    150     return 0;
    151 }
    View Code
  • 相关阅读:
    ElasticSearch 常用的查询过滤语句
    ElasticSearch的 Query DSL 和 Filter DSL
    photoshop CS 调整选择区域的大小
    pthread_once重塑singleton模式
    SGU536 Berland Chess
    怎样实现多线程
    [置顶] Linux下将Nutch1.3导入eclipse
    ENC28J60学习笔记——第1部分
    再看copy_on_write缩小临界区的例子
    leetcode Roman Integer
  • 原文地址:https://www.cnblogs.com/Blue233333/p/8793202.html
Copyright © 2011-2022 走看看