【树链剖分 ODT】cf1137F. Matches Are Not a Child's Play

孔爷的杂题系列;LCT清新题/ODT模板题

题目大意

定义一颗无根树的燃烧序列为:每次选取编号最小的叶子节点形成的序列。

要求支持操作:查询一个点$u$在燃烧序列中的排名;将一个点的编号变成最大

$n \le 200000$


题目分析

首先初始的燃烧序列容易构造,那么考虑进行一次up操作对序列会产生什么影响。

这里对$3$进行一次$up$,得到下图。

容易发现,记上一个版本序列最后一个元素为$las$,进行$up\,\,\,x$相当于是把路径$(las,x)$的答案变成从$las$到$x$的等差数列。因为$x$被$up$之后,这条路径只能从另一端的$las$走过来。

等差数列用线段树容易维护,这里讲一种ODT维护的方式:将路径$(las,x)$染为一种新颜色$c$,查询答案就是$1..c-1$颜色种类数+$dis(las,x)+1$.

那么就是一道难得的ODT+树剖模板题了。

关于下面132行的细节处理:写成root[i-1]=root[i]=u是因为对于初始序列,查询时候要保持dist(u, root[c-1])=0;但是对于之后修改的询问root[n]应该为n。

 

  1 #include<bits/stdc++.h>
  2 const int maxn = 200035;
  3 const int maxm = 400035;
  4 
  5 struct node
  6 {
  7     int l,r,val;
  8     node(int a=0, int b=0, int c=0):l(a),r(b),val(c) {}
  9     bool operator < (node a) const
 10     {
 11         return l < a.l;
 12     }
 13 };
 14 struct point
 15 {
 16     int fa,son,top,tot;
 17 }a[maxn];
 18 char opt[13];
 19 int n,m,tim,lst,chain[maxn],chTot,root[maxn<<1];
 20 int edgeTot,head[maxn],nxt[maxm],edges[maxm],deg[maxn],dep[maxn];
 21 std::set<node> s[maxn];
 22 std::priority_queue<int, std::vector<int>, std::greater<int> > q;
 23 typedef std::set<node>::iterator itr;
 24 namespace BIT
 25 {
 26     int f[maxn<<1];
 27     void add(int x, int c){for (x+=5; x<=n+m+5; x+=x&-x) f[x] += c;}
 28     int query(int x)
 29     {
 30         int ret = 0;
 31         for (x+=5; x; x-=x&-x) ret += f[x];
 32         return ret;
 33     }
 34 };
 35 
 36 int read()
 37 {
 38     char ch = getchar();
 39     int num = 0, fl = 1;
 40     for (; !isdigit(ch); ch=getchar())
 41         if (ch=='-') fl = -1;
 42     for (; isdigit(ch); ch=getchar())
 43         num = (num<<1)+(num<<3)+ch-48;
 44     return num*fl;
 45 }
 46 void addedge(int u, int v)
 47 {
 48     ++deg[u], ++deg[v];
 49     edges[++edgeTot] = v, nxt[edgeTot] = head[u], head[u] = edgeTot;
 50     edges[++edgeTot] = u, nxt[edgeTot] = head[v], head[v] = edgeTot;
 51 }
 52 void dfs1(int x, int fa)
 53 {
 54     a[x].fa = fa, a[x].tot = 1;
 55     a[x].son = a[x].top = -1, dep[x] = dep[fa]+1;
 56     for (int i=head[x]; i!=-1; i=nxt[i])
 57     {
 58         int v = edges[i];
 59         if (v==fa) continue;
 60         dfs1(v, x), a[x].tot += a[v].tot;
 61         if (a[x].son==-1||a[a[x].son].tot < a[v].tot) a[x].son = v;
 62     }
 63 }
 64 void dfs2(int x, int top)
 65 {
 66     if (x==top) s[x].insert(node(n+1, n+1, 0));
 67     chain[x] = ++chTot, a[x].top = top;
 68     if (a[x].son==-1) return;
 69     dfs2(a[x].son, top);
 70     for (int i=head[x]; i!=-1; i=nxt[i])
 71         if (edges[i]!=a[x].fa&&edges[i]!=a[x].son)
 72             dfs2(edges[i], edges[i]);
 73 }
 74 int Lca(int u, int v)
 75 {
 76     while (a[u].top!=a[v].top)
 77     {
 78         if (dep[a[u].top] > dep[a[v].top]) std::swap(u, v);
 79         v = a[a[v].top].fa;
 80     }
 81     if (dep[u] > dep[v]) std::swap(u, v);
 82     return u;
 83 }
 84 int dist(int u, int v)
 85 {
 86     int anc = Lca(u, v);
 87     return dep[u]+dep[v]-(dep[anc]<<1);
 88 }
 89 itr split(int i, int pos)
 90 {
 91     itr loc = s[i].lower_bound(node(pos));
 92     if (loc!=s[i].end()&&loc->l==pos) return loc;
 93     int l = (--loc)->l, r = loc->r, val = loc->val;
 94     s[i].erase(loc), s[i].insert(node(l, pos-1, val));
 95     return s[i].insert(node(pos, r, val)).first;
 96 }
 97 void insert(int i, int l, int r, int c)
 98 {
 99     itr rpos = split(i, r+1), lpos = split(i, l);
100     for (itr it=lpos; it!=rpos; ++it)
101         BIT::add(it->val, -(it->r-it->l+1));    //遍历清除历史颜色
102     s[i].erase(lpos, rpos);
103     BIT::add(c, r-l+1);
104     s[i].insert(node(l, r, c));
105 }
106 void chainModify(int u, int v)
107 {
108     while (a[u].top!=a[v].top)
109     {
110         if (dep[a[u].top] > dep[a[v].top]) std::swap(u, v);
111         insert(a[v].top, chain[a[v].top], chain[v], tim);
112         v = a[a[v].top].fa;
113     }
114     if (dep[u] > dep[v]) std::swap(u, v);
115     insert(a[u].top, chain[u], chain[v], tim);
116 }
117 int query(int u)
118 {
119     int c = split(a[u].top, chain[u])->val;
120     return BIT::query(c-1)+dist(u, root[c-1])+1;    //查询答案 root[c-1]是指上一个历史版本的最后一个元素las
121 }
122 int main()
123 {
124     memset(head, -1, sizeof head);
125     n = read(), m = read();
126     for (int i=1; i<n; i++) addedge(read(), read());
127     dfs1(1, 0), dfs2(1, 1);
128     for (int i=1; i<=n; i++)
129         if (deg[i]==1) q.push(i);
130     for (int i=1,u; i<=n; i++)
131     {
132         root[i-1] = root[i] = u = q.top(), q.pop();  //见上解释
133         BIT::add(i, 1), deg[u] = 0;
134         s[a[u].top].insert(node(chain[u], chain[u], ++tim));
135         for (int i=head[u]; i!=-1; i=nxt[i])
136             if ((--deg[edges[i]])==1) q.push(edges[i]);
137     }
138     for (int i=1; i<=m; i++)
139     {
140         scanf("%s",opt);
141         if (opt[0]=='u'){
142             int v = read();
143             root[++tim] = v;
144             chainModify(v, root[tim-1]);
145         }else if (opt[0]=='w') printf("%d\n",query(read()));
146         else{
147             int u = read(), v = read();
148             printf("%d\n",(query(u) < query(v))?u:v);
149         }
150     }
151     return 0;
152 }

 

 

END

posted @ 2019-04-05 21:56  AntiQuality  阅读(251)  评论(0编辑  收藏  举报