zoukankan      html  css  js  c++  java
  • 【树链剖分 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
    ",query(read()));
    146         else{
    147             int u = read(), v = read();
    148             printf("%d
    ",(query(u) < query(v))?u:v);
    149         }
    150     }
    151     return 0;
    152 }

    END

  • 相关阅读:
    POJ3667 Hotel 题解
    POJ1417 True Liars 题解
    POJ2482 Stars in Your Window 题解
    POJ1704 Georgia and Bob 题解
    矩阵运算
    P4778 Counting Swaps 题解
    poi解析office文档内容的工具类
    VMware安装Centos7超详细过程(图文)
    java后端树形菜单结构
    vue点击事件的修饰符
  • 原文地址:https://www.cnblogs.com/antiquality/p/10660122.html
Copyright © 2011-2022 走看看