• [luogu]P3250 [HNOI2016]网络


    原题链接:P3250 [HNOI2016]网络

    题意

    给定一棵无根树,m个操作
    0操作:增加一条a到b的权值为v的链
    1操作:删除第t个操作
    2操作:输出不经过x节点的权值最大的链

    分析

    数据结构神题。。。

    题目中要求维护不经过$x$节点的权值最大值,也就是说所有不经过$x$节点的链都能对答案产生贡献。

    也就是说,当增加一条链的时,除了链上的点,都应该增加价值为$v$的权值,答案就转化为了$x$点上的最大权值。

    我们可以线段树套堆……

    每个区间开一个堆,堆内存这段区间的权值。

    我们注意到堆需要支持删除操作。

    如何支持删除呢,我们可以开一个删除标志,维护每一个堆需要开两个堆,一个堆用于存插入的数据,另一个堆是已经被删掉的数据。

    如果两个堆顶一样,就一起$pop$掉,不然就输出第一个堆的堆顶。

    如果第一个堆为空输出$-1$。 

    由于堆的操作比较慢,而且插入和删除的操作区间是一样的,我这里直接标记永久化免去了下推标记操作。

    代码

      1 #include <bits/stdc++.h>
      2 const int N=2*1e5+1009;
      3 using namespace std;
      4 int read(){
      5     char c;int num,f=1;
      6     while(c=getchar(),!isdigit(c))if(c=='-')f=-1;num=c-'0';
      7     while(c=getchar(), isdigit(c))num=num*10+c-'0';
      8     return f*num;
      9 }
     10 struct Heap{
     11     priority_queue<int>rl,dl;
     12     void push(int x){rl.push(x);}
     13     void del(int x){
     14         dl.push(x);
     15         while(!dl.empty()&&dl.top()==rl.top()){
     16             dl.pop();rl.pop();
     17         }
     18     }
     19     int top(){
     20         while(!dl.empty()&&dl.top()==rl.top()){
     21             dl.pop();rl.pop();
     22         }
     23         if(rl.empty())return -1;
     24         return rl.top();
     25     }
     26 }tree[N*5];
     27 struct link{
     28     int x,y,v;
     29 }lk[N],tmp[N];
     30 int n,m;
     31 int head[N],nxt[N*2],ver[N*2],tot=1;
     32 int son[N],fa[N],siz[N],id[N],dep[N],top[N],tott=0;
     33 void DFS1(int x,int pre,int deep){
     34     dep[x]=deep;siz[x]=1;
     35     for(int i=head[x];i;i=nxt[i]){
     36         if(ver[i]==pre)continue;
     37         DFS1(ver[i],x,deep+1);
     38         fa[ver[i]]=x;
     39         siz[x]+=siz[ver[i]];
     40         if(siz[ver[i]]>siz[son[x]])son[x]=ver[i];
     41     }
     42 }
     43 void DFS2(int x,int ltp){
     44     id[x]=++tott;
     45     top[x]=ltp;
     46     if(!son[x])return ;
     47     DFS2(son[x],ltp);
     48     for(int i=head[x];i;i=nxt[i]){
     49         if(ver[i]==fa[x]||ver[i]==son[x])continue;
     50         DFS2(ver[i],ver[i]);
     51     }
     52 }
     53 //树链剖分
     54 
     55 void modify(int l,int r,int L,int R,int rt,int opt,int xx){
     56     if(L<=l&&r<=R){
     57         opt?tree[rt].del(xx):tree[rt].push(xx);
     58         return ;
     59     }
     60     int mid=(l+r)>>1;
     61     if(L<=mid)modify(l,mid,L,R,rt<<1,opt,xx);
     62     if(mid< R)modify(mid+1,r,L,R,rt<<1|1,opt,xx);
     63 }
     64 int query(int l,int r,int x,int rt){
     65     if(l==r)return tree[rt].top();
     66     int mid=(l+r)>>1,ans=tree[rt].top();
     67     if(x<=mid)return max(ans,query(l,mid,x,rt<<1));
     68     else return max(ans,query(mid+1,r,x,rt<<1|1));
     69 }
     70 void add_edge(int u,int v){
     71     ver[++tot]=v;nxt[tot]=head[u];head[u]=tot;
     72     ver[++tot]=u;nxt[tot]=head[v];head[v]=tot;
     73 }
     74 void Swap(int &x,int &y){x^=y;y^=x;x^=y;}
     75 bool cmp(link x,link y){
     76     if(x.x!=y.x)return x.x<y.x;
     77     return x.y<y.y;
     78 }
     79 void link_modify(int u,int v,int val,int opt){
     80     int cnt=0;
     81     while(top[u]!=top[v]){
     82         if(dep[top[u]]<dep[top[v]])Swap(u,v);
     83         tmp[++cnt].x=id[top[u]];
     84         tmp[  cnt].y=id[u];
     85         u=fa[top[u]];
     86     }
     87     if(id[u]>id[v])Swap(u,v);
     88     tmp[++cnt].x=id[u];
     89     tmp[  cnt].y=id[v];
     90     sort(tmp+1,tmp+1+cnt,cmp);
     91     int maxn=0;
     92     for(int i=1;i<=cnt;maxn=max(maxn,tmp[i++].y))
     93         if(maxn+1<tmp[i].x)modify(1,n,maxn+1,tmp[i].x-1,1,opt,val);
     94     if(maxn<n)modify(1,n,maxn+1,n,1,opt,val);
     95 }
     96 int main()
     97 {
     98     n=read();m=read();
     99     for(int i=1;i< n;i++)add_edge(read(),read());
    100     DFS1(1,1,1);DFS2(1,1);
    101     for(int i=1;i<=m;i++){
    102         int opt=read();
    103         if(opt==0){
    104             lk[i].x=read();
    105             lk[i].y=read();
    106             lk[i].v=read();
    107             link_modify(lk[i].x,lk[i].y,lk[i].v,opt);
    108         }else if(opt==1){
    109             int ttt=read();
    110             link_modify(lk[ttt].x,lk[ttt].y,lk[ttt].v,opt);
    111         }else {
    112             int a=read();
    113             printf("%d
    ",query(1,n,id[a],1));
    114         }
    115     }
    116     return 0;
    117 }
    View Code
  • 相关阅读:
    TRIGGERS_监测系统_多表视图触发器—向原始数据报表中插入数据
    PROCEDURE_监测系统_原始数据报表数据生成存储过程—求每天平均值插入多表视图
    PROCEDURE_监测系统_数据备份存储过程—备份原始数据,每十分钟一条,取平均值
    TRIGGERS_监测系统_原始数据表触发器—调用告警信息存储过程
    PROCEDURE_监测系统_告警信息存储过程—产生告警信息插入告警表
    秒(s) 毫秒(ms) 微秒(μs) 纳秒(ns) 皮秒(ps)及Java获得 .
    new String(byte[])和byte[]toString() 的区别
    Java 线程池 .
    加载配置文件的方式
    Spring的PropertyPlaceholderConfigurer应用
  • 原文地址:https://www.cnblogs.com/onglublog/p/10097316.html
Copyright © 2020-2023  润新知