zoukankan      html  css  js  c++  java
  • [HNOI2016]网络

    题目大意:
      给你一棵$n(nleq10^5)$的数,有$m(mleq2 imes10^5)$次操作,操作包含以下三种:
        1.新建一个从$u$到$v$的任务,权值为$w$;
        2.删除第$i$个任务;
        3.询问所有不经过$x$的任务中最大的权值。

    思路:
      树链剖分线段树套二叉堆。
      首先对树进行轻重链剖分,建立线段树。每个线段树结点套二叉堆,维护不经过这个结点的权值。因此对于操作1,我们可以先求LCA,同时求出路径上经过的所有链,修改没有经过的那一些链。对于操作2,暴力删除肯定会TLE,考虑另建一个堆来维护删除的那些权值。因此对于操作3,我们在取top时,先比较一下两个堆的top是否相同,如果相同就忽略掉。树链剖分LCA复杂度$O(log n)$,线段树复杂度$O(log n)$,二叉堆复杂度$O(log m)$,时间复杂度$O(mlog^2 nlog m)$。

    细节:
      二叉堆不能够用pb_ds中的配对堆代替,会MLE。

      1 #include<list>
      2 #include<queue>
      3 #include<cstdio>
      4 #include<cctype>
      5 #include<vector>
      6 #include<algorithm>
      7 inline int getint() {
      8     register char ch;
      9     while(!isdigit(ch=getchar()));
     10     register int x=ch^'0';
     11     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
     12     return x;
     13 }
     14 const int N=100001,M=200001;
     15 std::list<int> e[N];
     16 inline void add_edge(const int &u,const int &v) {
     17     e[u].push_back(v);
     18     e[v].push_back(u);
     19 }
     20 int dep[N],par[N],top[N],dfn[N],size[N],son[N];
     21 void dfs1(const int &x,const int &par) {
     22     size[x]=1;
     23     dep[x]=dep[::par[x]=par]+1;
     24     for(register std::list<int>::iterator i=e[x].begin();i!=e[x].end();i++) {
     25         const int &y=*i;
     26         if(y==par) continue;
     27         dfs1(y,x);
     28         size[x]+=size[y];
     29         if(size[y]>size[son[x]]) son[x]=y;
     30     }
     31 }
     32 void dfs2(const int &x) {
     33     dfn[x]=++dfn[0];
     34     top[x]=x==son[par[x]]?top[par[x]]:x;
     35     if(son[x]) dfs2(son[x]);
     36     for(register std::list<int>::iterator i=e[x].begin();i!=e[x].end();i++) {
     37         const int &y=*i;
     38         if(y==par[x]||y==son[x]) continue;
     39         dfs2(y);
     40     }
     41 }
     42 class SegmentTree {
     43     #define _left <<1
     44     #define _right <<1|1
     45     private:
     46         std::priority_queue<int> val[N<<2][2];
     47     public:
     48         void modify(const int &p,const int &b,const int &e,const int &l,const int &r,const int &x,const int &type) {
     49             if(b==l&&e==r) {
     50                 val[p][type].push(x);
     51                 return;
     52             }
     53             const int mid=(b+e)>>1;
     54             if(l<=mid) modify(p _left,b,mid,l,std::min(mid,r),x,type);
     55             if(r>mid) modify(p _right,mid+1,e,std::max(mid+1,l),r,x,type);
     56         }
     57         int query(const int &p,const int &b,const int &e,const int &x) {
     58             int ret=-1;
     59             while(!val[p][0].empty()&&val[p][0].top()==val[p][1].top()) {
     60                 val[p][0].pop();
     61                 val[p][1].pop();
     62             }
     63             if(!val[p][1].empty()) ret=val[p][1].top();
     64             if(b==e) return ret;
     65             const int mid=(b+e)>>1;
     66             if(x<=mid) ret=std::max(ret,query(p _left,b,mid,x));
     67             if(x>mid) ret=std::max(ret,query(p _right,mid+1,e,x));
     68             return ret;
     69         }
     70     #undef _left
     71     #undef _right
     72 };
     73 SegmentTree t;
     74 struct Path {
     75     int u,v,w;
     76 };
     77 Path p[M];
     78 std::vector<std::pair<int,int> > s;
     79 inline void modify(const int &id,const int &type) {
     80     int u=p[id].u,v=p[id].v;
     81     while(top[u]!=top[v]) {
     82         if(dep[top[u]]<dep[top[v]]) std::swap(u,v);
     83         s.push_back(std::make_pair(dfn[top[u]],dfn[u]));
     84         u=par[top[u]];
     85     }
     86     if(dep[u]<dep[v]) std::swap(u,v);
     87     s.push_back(std::make_pair(dfn[v],dfn[u]));
     88     s.push_back(std::make_pair(0,0));
     89     std::sort(s.begin(),s.end());
     90     s.push_back(std::make_pair(dfn[0]+1,0));
     91     for(register unsigned i=1;i<s.size();i++) {
     92         if(s[i-1].second+1<=s[i].first-1) t.modify(1,1,dfn[0],s[i-1].second+1,s[i].first-1,p[id].w,type);
     93     }
     94     s.clear();
     95 }
     96 inline int query(const int &x) {
     97     return t.query(1,1,dfn[0],dfn[x]);
     98 }
     99 int main() {
    100     const int n=getint(),m=getint();
    101     for(register int i=1;i<n;i++) {
    102         add_edge(getint(),getint());
    103     }
    104     dfs1(1,0);
    105     dfs2(1);
    106     for(register int i=1;i<=m;i++) {
    107         const int opt=getint();
    108         if(opt==0) {
    109             const int u=getint(),v=getint(),w=getint();
    110             p[i]=(Path){u,v,w};
    111             modify(i,1);
    112         }
    113         if(opt==1) modify(getint(),0);
    114         if(opt==2) printf("%d
    ",query(getint()));
    115     }
    116     return 0;
    117 }
  • 相关阅读:
    关于MQ的对比
    关于RabbitMQ(二)
    关于QPS、TPS、并发用户数、吞吐量的关系
    关于使用Ecplise构建gradle项目
    关于记录一次线上真实环境多线程引发的问题
    关于MySQL——find_in_set()函数的使用
    关于数据库的表连接
    关于Java线程池
    IntelliJ搭建Scala及Spark工程
    idea编写wordcount程序及spark-submit运行
  • 原文地址:https://www.cnblogs.com/skylee03/p/8496047.html
Copyright © 2011-2022 走看看