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

    [HNOI2016]网络

    树剖好题...

    首先他要求不受此影响的最大值.我们可以将题目中的链的补集都加上一个重要度,这样就可以单点查询最大值了.

    之后我们考虑如何给线段树加上一个重要度x,而且要求要能求出最大值.这里就想到STL中的大跟堆,其实set也行吧...

    对于线段树中的每一个点都对应一个堆,我们给点加上重要度时,直接让他进去大跟堆即可.

    之后怎么考虑撤销,我们如果直接q.pop()的话显然不行.我们考虑再见一个堆,将要删除的数加进去这个堆里.

    之后查询时,对比两个堆顶,相同的话都弹出即可.

    之后考虑怎么线段树区间覆盖,这里用lazy显然不行...既然如此我们就用标记永久化.

    其实简单看一下,标记永久化也没那么复杂,就是讲要覆盖的区间打上标记,在询问时一路累积标记即可.感觉和差分的询问时好像...

    这样我们就解决这道题了...好了,到次为止.

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int N=1e5+10;
    int n,m,link[N],tot;
    int dfn[N],pre[N],size[N],wson[N],top[N],deep[N],fa[N],num; 
    struct edge{int y,next;}a[N<<1];
    struct shu{int x,y,v;}b[N],c[N];
    priority_queue<int>q1[N<<2],q2[N<<2];
    struct Tree
    {
        int l,r;
        #define l(x) t[x].l
        #define r(x) t[x].r
    }t[N<<2];
    inline int read()
    {
        int x=0,ff=1;
        char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getchar();}
        while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
        return x*ff;
    }
    inline bool cmp(shu x,shu y){return x.x<y.x;}
    inline void add(int x,int y)
    {
        a[++tot].y=y;
        a[tot].next=link[x];
        link[x]=tot;
    }
    inline void dfs1(int x)
    {
        size[x]=1;
        for(int i=link[x];i;i=a[i].next)
        {
            int y=a[i].y;
            if(y==fa[x]) continue;
            fa[y]=x;deep[y]=deep[x]+1;
            dfs1(y);
            size[x]+=size[y];
            if(size[y]>size[wson[x]]) wson[x]=y;
        }
    }
    inline void dfs2(int x,int tp)
    {
        dfn[x]=++num;
        pre[num]=x;
        top[x]=tp;
        if(wson[x]) dfs2(wson[x],tp);
        for(int i=link[x];i;i=a[i].next)
        {
            int y=a[i].y;
            if(y==fa[x]||y==wson[x]) continue;
            dfs2(y,y);
        }
    }
    inline void build(int p,int l,int r)
    {
        l(p)=l,r(p)=r;
        if(l==r) return;
        int mid=l+r>>1;
        build(p<<1,l,mid);
        build(p<<1|1,mid+1,r);
    }
    inline void Tree_alter(int p,int l,int r,int v,int op)
    {
        if(l==l(p)&&r==r(p))
        {
            if(op==1) q1[p].push(v);
            else      q2[p].push(v); 
            return;
        }
        int mid=l(p)+r(p)>>1;
        if(r<=mid) Tree_alter(p<<1,l,r,v,op);
        else if(l>mid) Tree_alter(p<<1|1,l,r,v,op);
        else Tree_alter(p<<1,l,mid,v,op),Tree_alter(p<<1|1,mid+1,r,v,op);
    }
    inline void solve1(int a,int b,int v,int op)
    {
        int o=0;
        while(top[a]!=top[b])
        {
            if(deep[top[a]]>deep[top[b]]) swap(a,b);
            c[++o].x=dfn[top[b]];c[o].y=dfn[b];
            b=fa[top[b]];
        }
        if(deep[a]>deep[b]) swap(a,b);
        c[++o].x=dfn[a];c[o].y=dfn[b];
        sort(c+1,c+o+1,cmp);
        //for(int i=1;i<=o;++i) cout<<c[i].x<<' '<<c[i].y<<endl;
        if(c[1].x!=1) Tree_alter(1,1,c[1].x-1,v,op);
        for(int i=1;i<o;++i)
            if(c[i+1].x-c[i].y!=1) Tree_alter(1,c[i].y+1,c[i+1].x-1,v,op);
        if(c[o].y!=n) Tree_alter(1,c[o].y+1,n,v,op);
    }
    inline int Tree_ask(int p,int x)
    {
        while(!q1[p].empty()&&!q2[p].empty()&&q1[p].top()==q2[p].top()) 
            q1[p].pop(),q2[p].pop();
        int ans=q1[p].empty()?-1:q1[p].top();
        if(l(p)==r(p)) return ans;
        int mid=l(p)+r(p)>>1;
        if(x<=mid) ans=max(ans,Tree_ask(p<<1,x));
        else       ans=max(ans,Tree_ask(p<<1|1,x));
        return ans;
    }
    int main()
    {
        freopen("1.in","r",stdin);
        n=read();m=read();
        for(int i=1;i<n;++i)
        {
            int x=read(),y=read();
            add(x,y);add(y,x);
        }
        dfs1(1);dfs2(1,1);
        build(1,1,n);
    //    for(int i=1;i<=n;++i) cout<<i<<' '<<dfn[i]<<endl;
        for(int i=1;i<=m;++i)
        {
            int type=read();
            if(!type)
            {
                int x=read(),y=read(),v=read();
                b[i].x=x;b[i].y=y;b[i].v=v;
                solve1(x,y,v,1);
            }
            else if(type==1)
            {
                int x=read();
                solve1(b[x].x,b[x].y,b[x].v,-1);
            }
            else if(type==2)
            {
                int x=read();
                printf("%d
    ",Tree_ask(1,dfn[x]));
            }    
        }
        return 0;
    }
    View Code
  • 相关阅读:
    PL/SQL Developer连接Oracle
    Oracle 11g 监听命令
    Oracle 11g的登陆问题
    PL/SQL Developer 配置和使用
    KMP应用求两个字符串的最长公共子串
    msc pool概念
    nformix调优之执行计划取得
    lsof 与fuser
    informix onstat命令收集
    各类系统上查看占cpu最多的进程
  • 原文地址:https://www.cnblogs.com/gcfer/p/12573494.html
Copyright © 2011-2022 走看看