• [CodeChef-LVGFT]Lovers Gift


    题目大意:
      给定一个$n(nle10^5)$个结点的树,初始全为白点。$m(mle10^5)$次操作,每次将点$x$染成黑色或询问从$x$出发至少经过一个黑点能到达的点中,编号次大的点。

    思路:
      将操作倒序处理,即原操作变为擦除颜色和询问两种操作。用并查集维护白点连通块和若干单独的黑点。记录每个连通块或黑点出发至少经过一个黑点能到达的点中,能到达的最大和次大的点。擦除黑点时进行合并即可。维护最大、次大点时选择答案较小的连通块暴力递减。递减次数加起来是$n$。初始时每个连通块维护的最大值都是$n$,次大值都是$n-1$。而只有当连通块的点中含有$n$或$n-1$时,答案才会变小。每次合并时从两个连通块中答案比较小的往下枚举,总共最多枚举$2n$次。时间复杂度$O((n+m)alpha(n)$比标算不知道高到哪里去了。

     1 #include<cstdio>
     2 #include<cctype>
     3 #include<algorithm>
     4 inline int getint() {
     5     register char ch;
     6     while(!isdigit(ch=getchar()));
     7     register int x=ch^'0';
     8     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
     9     return x;
    10 }
    11 const int N=1e5+1,M=1e5+1;
    12 struct Edge {
    13     int to,next;
    14 };
    15 Edge e[N<<1];
    16 int h[N],b[N],ans[N];
    17 inline void add_edge(const int &u,const int &v) {
    18     e[++h[0]]=(Edge){v,h[u]};h[u]=h[0];
    19     e[++h[0]]=(Edge){u,h[v]};h[v]=h[0];
    20 }
    21 std::pair<bool,int> q[M];
    22 struct DisjointSet {
    23     int anc[N];
    24     void reset(const int &n) {
    25         for(register int i=1;i<=n;i++) anc[i]=i;
    26     }
    27     int find(const int &x) {
    28         return x==anc[x]?x:anc[x]=find(anc[x]);
    29     }
    30     void merge(const int &x,const int &y) {
    31         anc[find(x)]=find(y);
    32     }
    33     bool same(const int &x,const int &y) {
    34         return find(x)==find(y);
    35     }
    36 };
    37 DisjointSet s;
    38 std::pair<int,int> max[N];
    39 inline void maintain(const int &x) {
    40     while(max[x].first&&s.same(x,max[x].first)) max[x].first--;
    41     max[x].second=std::max(std::min(max[x].second,max[x].first-1),0);
    42     while(max[x].second&&s.same(x,max[x].second)) max[x].second--;
    43 }
    44 int main() {
    45     for(register int T=getint();T;T--) {
    46         const int n=getint(),m=getint();
    47         std::fill(&h[0],&h[n]+1,-1);
    48         for(register int i=1;i<n;i++) {
    49             add_edge(getint(),getint());
    50         }
    51         for(register int i=1;i<=m;i++) {
    52             const bool opt=getint()&1;
    53             const int x=getint();
    54             if(opt&&!b[x]) b[x]=i;
    55             q[i]={opt,x};
    56         }
    57         s.reset(n);
    58         std::fill(&max[1],&max[n]+1,std::make_pair(n,n-1));
    59         for(register int i=1;i<=n;i++) {
    60             if(!b[i]) maintain(i);
    61         }
    62         for(register int x=1;x<=n;x++) {
    63             if(b[x]) continue;
    64             for(register int i=h[x];~i;i=e[i].next) {
    65                 const int &y=e[i].to;
    66                 if(b[y]||s.same(x,y)) continue;
    67                 max[s.find(y)]=std::min(max[s.find(y)],max[s.find(x)]);
    68                 s.merge(x,y);
    69                 maintain(s.find(x));
    70             }
    71         }
    72         for(register int i=m;i;i--) {
    73             const bool opt=q[i].first;
    74             const int x=q[i].second;
    75             if(opt&&b[x]==i) {
    76                 b[x]=0;
    77                 maintain(s.find(x));
    78                 for(register int i=h[x];~i;i=e[i].next) {
    79                     const int &y=e[i].to;
    80                     if(b[y]||s.same(x,y)) continue;
    81                     max[s.find(y)]=std::min(max[s.find(y)],max[s.find(x)]);
    82                     s.merge(x,y);
    83                     maintain(s.find(x));
    84                 }
    85             }
    86             if(!opt) {
    87                 ans[i]=max[s.find(x)].second?:-1;
    88             }
    89         }
    90         for(register int i=1;i<=m;i++) {
    91             if(!q[i].first) printf("%d
    ",ans[i]);
    92         }
    93     }
    94     return 0;
    95 }
  • 相关阅读:
    Chrome浏览器的下拉选择框option有黑框的问题
    修改input checkbox和radio默认样式
    VsCode安装cssrem插件实现px转rem
    js实现小球的弹性碰撞
    CSS 技巧 -- 不定宽溢出文本适配滚动
    记忆化递归和递推
    DOM事件中target和currentTarget的区别
    TypeScripy + Vue Property Decorator + Vue Router,组件内的导航守卫无效
    行内元素没有内容时设置默认的宽高
    焦点元素,添加半透明遮罩
  • 原文地址:https://www.cnblogs.com/skylee03/p/8915809.html
Copyright © 2020-2023  润新知