• BZOJ 3083 遥远的国度 树链剖分


    3083: 遥远的国度

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 797  Solved: 181
    [Submit][Status]

    Description

    描述
    zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度。当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要zcwwzdjn完成任务后才能进入遥远的国度继续追杀。

    问题是这样的:遥远的国度有n个城市,这些城市之间由一些路连接且这些城市构成 了一颗树。这个国度有一个首都,我们可以把这个首都看做整棵树的根,但遥远的国度比较奇怪,首都是随时有可能变为另外一个城市的。遥远的国度的每个城市有 一个防御值,有些时候RapiD会使得某两个城市之间的路径上的所有城市的防御值都变为某个值。RapiD想知道在某个时候,如果把首都看做整棵树的根的 话,那么以某个城市为根的子树的所有城市的防御值最小是多少。由于RapiD无法解决这个问题,所以他拦住了zcwwzdjn希望他能帮忙。但 zcwwzdjn还要追杀sb的zhx,所以这个重大的问题就被转交到了你的手上。

    Input

    第1行两个整数n m,代表城市个数和操作数。
    第2行至第n行,每行两个整数 u v,代表城市u和城市v之间有一条路。
    第n+1行,有n个整数,代表所有点的初始防御值。
    第n+2行一个整数 id,代表初始的首都为id。
    第n+3行至第n+m+2行,首先有一个整数opt,如果opt=1,接下来有一个整数id,代表把首都修改为id;如果opt=2,接下来有三个整数 p1 p2 v,代表将p1 p2路径上的所有城市的防御值修改为v;如果opt=3,接下来有一个整数 id,代表询问以城市id为根的子树中的最小防御值。

    Output


    对于每个opt=3的操作,输出一行代表对应子树的最小点权值。

    Sample Input

    3 7
    1 2
    1 3
    1 2 3
    1
    3 1
    2 1 1 6
    3 1
    2 2 2 5
    3 1
    2 3 3 4
    3 1

    Sample Output

    1
    2
    3
    4
    提示
    对于20%的数据,n<=1000 m<=1000。
    对于另外10%的数据,n<=100000,m<=100000,保证修改为单点修改。
    对于另外10%的数据,n<=100000,m<=100000,保证树为一条链。
    对于另外10%的数据,n<=100000,m<=100000,没有修改首都的操作。
    对于100%的数据,n<=100000,m<=100000,0<所有权值<=2^31。
     
     
     

    思路来自hja,劲爆的读入优化来自zhonghaoxi,基本自己没想什么,还Wa了很久。

    主要就是树链剖分。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cctype>
    using namespace std;
    #define INF 0x3f3f3f3f
    #define MAXN 110000
    #define lch (now<<1)
    #define rch (now<<1^1)
    typedef long long qword;
    #ifdef unix
    #define LL "%d"
    #else
    #define LL "%I64d"
    #endif
    
      
    const int BUF_SIZE = 30;
    char buf[BUF_SIZE], *buf_s = buf, *buf_t = buf + 1;
    #define PTR_NEXT() 
    { 
            buf_s ++; 
            if (buf_s == buf_t) 
            { 
                    buf_s = buf; 
                    buf_t = buf + fread(buf, 1, BUF_SIZE, stdin); 
            } 
    }
    
    #define readint(_n_) 
    { 
            while (*buf_s != '-' && !isdigit(*buf_s)) 
            PTR_NEXT(); 
            bool register _nega_ = false; 
            if (*buf_s == '-') 
            { 
                    _nega_ = true; 
                    PTR_NEXT(); 
            } 
            int register _x_ = 0; 
            while (isdigit(*buf_s)) 
            { 
                    _x_ = _x_ * 10 + *buf_s - '0'; 
                    PTR_NEXT(); 
            } 
            if (_nega_) 
            _x_ = -_x_; 
            (_n_) = (_x_); 
    }
    int n,m;
    int val_t[MAXN];
    //segment_tree{{{
    struct segt
    {
            int l,r,val;
            int tag;
    }tree[MAXN*4];
    int ptr[MAXN];
    void down(int now)
    {
            if (tree[now].tag!=INF)
            {
                    tree[lch].val=tree[rch].val=tree[lch].tag=tree[rch].tag=tree[now].tag;
                    tree[now].tag=INF;
            }
    }
    void update(int now)
    {
            if (tree[now].l==tree[now].r)return ;
            tree[now].val=min(tree[lch].val,tree[rch].val);
    }
    void build_tree(int now,int l,int r)
    {
            tree[now].l=l;
            tree[now].r=r;
            tree[now].tag=INF;
            if (l==r){
                    ptr[l]=now;
                    tree[now].val=val_t[l];
                    return;
            }
            int mid=(l+r)>>1;
            build_tree(lch,l,mid);
            build_tree(rch,mid+1,r);
            update(now);
    }
    /*
       void set_val(int pos,int val)
       {
       pos=ptr[pos];
       tree[pos].val=val;
       while (pos)
       {
       update(pos);
       pos>>=1;
       }
       }*/
    void set_seg(int now,int l,int r,int val)
    {
            down(now);
            if (tree[now].l==l&&tree[now].r==r)
            {
                    tree[now].val=val;
                    tree[now].tag=val;
                    return ;
            }
            int mid=(tree[now].l+tree[now].r)>>1;
            if (r<=mid)
            {
                    set_seg(lch,l,r,val);
                    update(now);
                    return ;
            }
            if (mid<l)
            {
                    set_seg(rch,l,r,val);
                    update(now);
                    return ;
            }
            set_seg(lch,l,mid,val);
            set_seg(rch,mid+1,r,val);
            update(now);
    
    }
    int query_min(int now,int l,int r)
    {
            down(now);
            if (tree[now].l==l&&tree[now].r==r)
            {
                    return tree[now].val;
            }
            int mid;
            mid=(tree[now].l+tree[now].r)>>1;
            if (r<=mid)
            {
                    return query_min(lch,l,r);
            }
            if (mid<l)
            {
                    return query_min(rch,l,r);
            }
            return min(query_min(lch,l,mid),query_min(rch,mid+1,r));
    }
    //}}}
    struct Edge
    {
            int np;
            Edge *next;
    }E[MAXN*2],*V[MAXN];
    int root,tope=-1;
    void addedge(int x,int y)
    {
            E[++tope].np=y;
            E[tope].next=V[x];
            V[x]=&E[tope];
    }
    int dfn[MAXN],l[MAXN],fa[MAXN],inp[MAXN],oup[MAXN];
    int depth[MAXN];
    int cnt=0;
    int siz_s[MAXN],son[MAXN];
    int siz_t[MAXN];
    int top[MAXN];
    int dfs(int now,int dep)
    {
            Edge *ne;
            int t;
            siz_s[now]=0;
            siz_t[now]=1;
            depth[now]=dep;
            for (ne=V[now];ne;ne=ne->next)
            {
                    if (fa[now]!=ne->np)
                    {
                            fa[ne->np]=now;
                            t=dfs(ne->np,dep+1);
                            siz_t[now]+=t;
                            if (t>siz_s[now])
                            {
                                    siz_s[now]=t;
                                    son[now]=ne->np;
                            }
                    }
            }
            return siz_t[now];
    }
    void dfs2(int now,int tp)
    {
            Edge *ne;
            dfn[now]=++cnt;
            inp[now]=cnt;
            l[cnt]=val_t[now];
            top[now]=tp;
            if (son[now])dfs2(son[now],tp);
            for (ne=V[now];ne;ne=ne->next)
            {
                    if (fa[now]!=ne->np&&son[now]!=ne->np)
                    {
                            dfs2(ne->np,ne->np);
                    }
            }
            oup[now]=cnt;
    }
    int jump[20][MAXN],topj;
    void init_lca()
    {
            int i,j;
            for (i=1;i<=n;i++)jump[0][i]=fa[i];
            bool flag=true;
            for (i=1;i<20&&flag;i++)
            {
                    flag=false;
                    topj=i;
                    for (j=1;j<=n;j++)
                    {
                            jump[i][j]=jump[i-1][jump[i-1][j]];
                            if (jump[i][j]!=root)flag=true;
                    }
            }
    }
    void swim(int &x,int l)
    {
            int i=0;
            while (l)
            {
                    if (l&1)x=jump[i][x];
                    i++;
                    l>>=1;
            }
    }
    int lca(int x,int y)
    {
            if (depth[x]<depth[y])
            {
                    swim(y,depth[y]-depth[x]);
            }
            if (depth[x]>depth[y])
            {
                    swim(x,depth[x]-depth[y]);
            }
            if (x==y)return x;
            for (int i=topj;i>=0;i--)
            {
                    if (jump[i][x]!=jump[i][y])
                    {
                            x=jump[i][x];
                            y=jump[i][y];
                    }
            }
            return fa[x];
    }
    int id;
    int main()
    {
            freopen("input.txt","r",stdin);
            //freopen("output2.txt","w",stdout);
            //scanf("%d%d",&n,&m);
            readint(n);
            readint(m);
            int i,j,k,x,y,z;
            int a;
            for (i=1;i<n;i++)
            {
                    //scanf("%d%d",&x,&y);
                    readint(x);
                    readint(y);
                    addedge(x,y);
                    addedge(y,x);
            }
            root=1;
            fa[root]=root;
            dfs(root,1);
            dfs2(root,root);
            init_lca();
            for (i=1;i<=n;i++)
            {
                    readint(x);
                    //scanf("%d",&x);
                    val_t[dfn[i]]=x;
            }
            build_tree(1,1,cnt);
            readint(id);
            //scanf("%d",&id);
            int opt,ans;
            //cout<<"a";
            for (i=0;i<m;i++)
            {
                    //scanf("%d",&opt);
                    readint(opt);
                    if (opt==1)
                    {
                            //scanf("%d",&id);
                            readint(id);
                    }
                    if (opt==2)
                    {
                            //scanf("%d%d%d",&x,&y,&z);
                            readint(x);
                            readint(y);
                            readint(z);
                            while (top[x]!=top[y])
                            {
                                    if (depth[top[x]]<depth[top[y]])swap(x,y);
                                    set_seg(1,dfn[top[x]],dfn[x],z);
                                    x=fa[top[x]];
                            }
                            if (dfn[x]<dfn[y])
                            {
                                    set_seg(1,dfn[x],dfn[y],z);
                            }else
                            {
                                    set_seg(1,dfn[y],dfn[x],z);
                            }
                    }
                    if (opt==3)
                    {
                            //scanf("%d",&x);
                            readint(x);
                            if (x==id)
                            {
                                    ans=query_min(1,1,n);
                                    printf("%d
    ",ans);
                                    continue;
                            }
                            if (x==root)
                            {
    LABEL2:
                                    y=id;
                                    /*    for (j=topj;j>=0;j--)
                                        {
                                        if (jump[j][y]!=x)
                                        {
                                        y=jump[j][y];
                                        }
                                        }*/
                                    swim(y,depth[y]-depth[x]-1);
                                    ans=INF;
                                    if (inp[y]!=1)ans=query_min(1,1,inp[y]-1);
                                    if (oup[y]!=n)ans=min(ans,query_min(1,oup[y]+1,n));
                                    printf("%d
    ",ans);
                                    continue;
                            }
                            if (depth[x]>=depth[id])
                            {
    LABEL1:
                                    ans=query_min(1,inp[x],oup[x]);
                                    printf("%d
    ",ans);
                                    continue;
                            }
                            if (lca(x,id)==x)
                            {
                                    /*        ans=INF;
                                            ans=query_min(1,1,inp[x]);
                                            if (oup[x]!=n)ans=min(ans,query_min(1,oup[x]+1,n));
                                            printf("%d
    ",ans);*/
                                    goto LABEL2;
                                    continue;
                            }else
                            {
                                    goto LABEL1;
                            }
                    }
                    //            cout<<opt<<" "<<x<<" "<<y<<endl;
            }
    
    
    }
    by mhy12345(http://www.cnblogs.com/mhy12345/) 未经允许请勿转载

    本博客已停用,新博客地址:http://mhy12345.xyz

  • 相关阅读:
    SQL------Hint
    JVM——垃圾回收
    JVM——内存结构
    SpringMVC——拦截器,过滤器实现登录拦截
    SpringMVC——参数传递
    SpringMVC——数据乱码问题
    SpringMVC——MVC执行流程底层剖析
    Spring——5种增强方式
    Spring——bean的五种作用域和生命周期
    Spring——多种方式实现依赖注入
  • 原文地址:https://www.cnblogs.com/mhy12345/p/3787222.html
Copyright © 2020-2023  润新知