[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 }
原文地址:https://www.cnblogs.com/skylee03/p/8496047.html