zoukankan      html  css  js  c++  java
  • QTREE 树链剖分---模板 spoj QTREE

    《树链剖分及其应用》 一文讲得非常清楚,我一早上就把他学会了并且A了这题的入门题。

    spoj QTREE

    题目:

    给出一棵树,有两种操作:

    1.修改一条边的边权。

    2.询问节点a到b的最大边权。

    直接粘代码。更成熟的代码可以看下一篇BZOJ 1036: [ZJOI2008]树的统计Count

    #include <set>
    #include <map>
    #include <list>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <string>
    #include <vector>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    typedef long long ll;
    typedef unsigned long long ull;
    
    #define debug puts("here")
    #define rep(i,n) for(int i=0;i<n;i++)
    #define rep1(i,n) for(int i=1;i<=n;i++)
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define foreach(i,vec) for(unsigned i=0;i<vec.size();i++)
    #define pb push_back
    #define RD(n) scanf("%d",&n)
    #define RD2(x,y) scanf("%d%d",&x,&y)
    #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)
    #define RD4(x,y,z,w) scanf("%d%d%d%d",&x,&y,&z,&w)
    #define All(vec) vec.begin(),vec.end()
    #define MP make_pair
    #define PII pair<int,int>
    #define PQ priority_queue
    #define cmax(x,y) x = max(x,y)
    #define cmin(x,y) x = min(x,y)
    #define Clear(x) memset(x,0,sizeof(x))
    /*
    
    #pragma comment(linker, "/STACK:1024000000,1024000000")
    
    int size = 256 << 20; // 256MB
    char *p = (char*)malloc(size) + size;
    __asm__("movl %0, %%esp
    " :: "r"(p) );
    
    */
    
    /******** program ********************/
    
    const int MAXN = 100005;
    
    int val[MAXN];
    int po[MAXN],tol;
    bool use[MAXN];
    int n;
    
    struct node{
        int y,c,next;
    }edge[MAXN];
    
    inline void add(int x,int y,int c){
        edge[++tol].y = y;
        edge[tol].c = c;
        edge[tol].next = po[x];
        po[x] = tol;
    }
    
    struct tc{ // tree chain subdivision
        int sz;     // x子树大小
        int dep;    // 节点x的深度
        int top;    // 节点x所在链的顶端节点
        int fa;     // 节点x的父亲
        int son;    // 重儿子
        int tid;    // 在线段树中的位置
    }p[MAXN];
    
    void dfsFind(int x,int fa,int dep){
        use[x] = true;
        p[x].dep = dep;
        p[x].sz = 1;
        p[x].son = 0;
        p[x].fa = fa;
    
        int mx = 0;
        for(int i=po[x];i;i=edge[i].next){
            int y = edge[i].y;
            if(use[y])continue;
            dfsFind(y,x,dep+1);
            p[x].sz += p[y].sz;
            if(p[y].sz>mx){
                p[x].son = y;
                mx = p[y].sz;
            }
        }
    }
    
    int tid;
    void dfsCon(int x,int fa){
        use[x] = true;
        p[x].tid = ++ tid;
        p[x].top = fa;
        if(p[x].son)
            dfsCon(p[x].son,fa);
        for(int i=po[x];i;i=edge[i].next){
            int y = edge[i].y;
            if(use[y])continue;
            dfsCon(y,y);
        }
    }
    
    struct Tree{
        int l,r,mx;
        inline int mid(){
            return (l+r)>>1;
        }
    }tree[MAXN<<2];
    
    inline void update(int rt){
        tree[rt].mx = max(tree[rt<<1].mx,tree[rt<<1|1].mx);
    }
    
    void build(int l,int r,int rt){
        tree[rt].l = l;
        tree[rt].r = r;
        if(l==r){
            tree[rt].mx = val[l];
            return;
        }
        int mid = tree[rt].mid();
        build(l,mid,rt<<1);
        build(mid+1,r,rt<<1|1);
    
        update(rt);
    }
    
    void modify(int pos,int c,int rt){
        if(tree[rt].l==tree[rt].r){
            tree[rt].mx = c;
            return;
        }
        int mid = tree[rt].mid();
        if(pos<=mid)
            modify(pos,c,rt<<1);
        else
            modify(pos,c,rt<<1|1);
    
        update(rt);
    }
    
    int ask(int l,int r,int rt){
        if(tree[rt].l==l&&tree[rt].r==r)
            return tree[rt].mx;
        int mid = tree[rt].mid();
        if(r<=mid)
            return ask(l,r,rt<<1);
        else if(l>mid)
            return ask(l,r,rt<<1|1);
        else
            return max( ask(l,mid,rt<<1),ask(mid+1,r,rt<<1|1) );
    }
    
    int main(){
    
    #ifndef ONLINE_JUDGE
        freopen("sum.in","r",stdin);
        //freopen("sum.out","w",stdout);
    #endif
    
        int x,y,z,ncase;
        RD(ncase);
        while(ncase--){
            RD(n);
            Clear(po);
            tol = 1;
    
            REP(i,2,n){
                RD3(x,y,z);
                add(x,y,z);
                add(y,x,z);
            }
    
            Clear(use);
            dfsFind(1,1,1);
    
            tid = 0;
            Clear(use);
            dfsCon(1,1);
    
            for(int i=2;i<tol;i+=2){
                int x = edge[i^1].y; // 对应于第x条边的节点 (x,y)
                int y = edge[i].y;
    
                if(p[x].dep>p[y].dep)
                    val[ p[x].tid ] = edge[i].c;
                else
                    val[ p[y].tid ] = edge[i].c;
            }
    
            build(2,n,1);
    
            char op[10];
            while(scanf("%s",op),op[0]!='D'){
    
                if(op[0]=='C'){
                    RD2(x,z);
                    y = edge[x<<1].y;
                    x = edge[x<<1|1].y;
    
                    if( p[x].dep>p[y].dep )
                        modify( p[x].tid,z,1 );
                    else
                        modify( p[y].tid,z,1 );
                }else{
                    RD2(x,y);
                    int ans = -(1<<30);
                    while( p[x].top != p[y].top ){
                        if( p[ p[x].top ].dep < p[ p[y].top ].dep )
                            swap(x,y);
                        ans = max(ans,ask(p[ p[x].top ].tid,p[x].tid,1));
                        x = p[ p[x].top ].fa;
                    }
                    if(p[x].dep>p[y].dep)
                        swap(x,y);
                    if(x!=y)
                        ans = max(ans,ask(p[x].tid+1,p[y].tid,1));
                    printf("%d
    ",ans);
                }
            }
        }
    
        return 0;
    }
  • 相关阅读:
    EasyNVR流媒体服务器网页兼容调试:ie浏览器下的接口调用成功但页面无法显示实时的数据
    EasyNVR流媒体服务器网页兼容调试:ie浏览器下的接口调用成功但页面无法显示实时的数据
    实现RTSP网站微信直播方案EasyNVR(linux版)部署问题之:ERR_CONTENT_LENGTH_MISMATCH
    实现RTSP网站微信直播方案EasyNVR(linux版)部署问题之:ERR_CONTENT_LENGTH_MISMATCH
    RTSP转RTMP-HLS网页无插件视频直播-EasyNVR功能介绍-音频开启
    rtsp转rtmp、hls网页直播服务器EasyNVR前端兼容性调试:ie下的 pointer-events- none
    RTSP转RTMP-HLS网页无插件视频直播-EasyNVR功能介绍-音频开启
    rtsp转rtmp、hls网页直播服务器EasyNVR前端兼容性调试:ie下的 pointer-events- none
    EasyNVR无插件流媒体服务器前端技术防止重复提交的方法
    EasyNVR无插件流媒体服务器前端技术防止重复提交的方法
  • 原文地址:https://www.cnblogs.com/yejinru/p/3279179.html
Copyright © 2011-2022 走看看