zoukankan      html  css  js  c++  java
  • 18寒假第三测

    第一题:找LCA,两点之间的距离=他们各自到起点的距离 - 2*LCA到起点的距离

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 100015, P = 20;
    
    
    int head[2 * maxn],to[2 * maxn],last[2 *maxn],co[2 * maxn],dep[maxn], idx, anc[maxn][P+1],dis[maxn];
    void dfs(int u,int from){
        //in[u] = ++idx;    
        anc[u][0] = from;
        for(int p = 1; p <= P; p++)
            anc[u][p] = anc[anc[u][p-1]][p-1];
        for(int i = head[u]; i; i = last[i]){
            if(to[i] != from){
                dep[to[i]] = dep[u] + 1;
                dis[to[i]] = dis[u] + co[i];
                dfs(to[i], u);
            }
        }
    }
    void adde(int u,int v,int w){
        idx++;
        last[idx] = head[u];
        to[idx] = v;    
        co[idx] = w;
        head[u] = idx;
    }
    int lca(int u,int v){
        if(dep[u] < dep[v])swap(u, v);
        int t = dep[u] - dep[v];
        for(int p = 0; t; t >>= 1, p++)
            if(t & 1)u = anc[u][p];
        if(u == v)return v;
        
        for(int p = P; p >=0; p--)
            if(anc[u][p] != anc[v][p])
                u = anc[u][p], v = anc[v][p];
        return anc[u][0];
    }
    int main(){
        freopen ( "distance.in", "r", stdin ) ;
        freopen ( "distance.out", "w", stdout ) ;
        int n,m;
        cin>>n;
        for(int i=1;i<n;i++){
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            adde( u, v, w );
            adde( v, u, w );
        }
        
        dfs(1,1);
        cin>>m;
        for(int i=1;i<=m;i++){
            int u ,v;
            scanf("%d%d",&u,&v);
            int q = lca(u,v);
            printf("%d
    ",dis[v]+dis[u]-dis[q]*2);
        }
        
        
        
    }

    第二题:先dfs的dfn序,再投影得到一个序列,建线段树

    #include<bits/stdc++.h>
    using namespace std;
    
    const int oo = 0x3f3f3f3f;
    
    #define MAX_N 100005
    long long sum ;
    int head[MAX_N<<1],next[MAX_N<<1],to[MAX_N<<1];
    int tot, a[MAX_N], in[MAX_N], out[MAX_N],dep[MAX_N],n, m, idx;
    void dfs(int u,int from){
        in[u] = ++idx;
        for(int i = head[u]; i; i = next[i]){
            int v = to[i];
            if(v != from){
                dep[v] = dep[u] + 1;
                dfs(v,u);
            }
        }
        out[u] = idx;
    }
    
    void adde(int u,int v){
        ++tot;
        next[tot] = head[u];
        to[tot] = v;
        head[u] = tot;
            
    }
    
    struct SegTree{
        struct node{
            long long sum;
            int vmin,vmax,lazy;
        };
        node Tree[MAX_N << 2];
        
        #define ls l, m, v << 1
        #define rs m+1, r, v << 1 | 1
        void push_up(int v){
            Tree[v].sum = Tree[v << 1].sum + Tree[v << 1 | 1].sum;
            Tree[v].vmin = min(Tree[v << 1].vmin, Tree[v << 1 | 1].vmin);
            Tree[v].vmax = max(Tree[v << 1].vmax, Tree[v << 1 | 1].vmax);    
        }
        void push_down(int l, int r, int v){
            int m = (l + r) >> 1;
            
            Tree[v << 1].sum += 1LL * Tree[v].lazy * (m - l +1);
            Tree[v << 1].vmin += Tree[v].lazy;
            Tree[v << 1].vmax += Tree[v].lazy;
            Tree[v << 1].lazy += Tree[v].lazy;
            
            Tree[v << 1 | 1].sum += 1LL * Tree[v].lazy * (r - m);
            Tree[v << 1 | 1].vmin += Tree[v].lazy;
            Tree[v << 1 | 1].vmax += Tree[v].lazy;
            Tree[v << 1 | 1].lazy += Tree[v].lazy;
            
            Tree[v].lazy = 0;
        }    
        void modify(int x,int L,int R,int l = 1, int r = n, int v = 1){
            if(l >= L && r <= R){
                Tree[v].lazy += x;
                Tree[v].sum += 1LL * x * (r - l + 1);
                Tree[v].vmin += x;
                Tree[v].vmax += x;            
            }
            else {
                if(Tree[v].lazy)push_down(l,r,v);
                int m = (l + r) / 2;
                if(L <= m)modify(x,L,R,ls);
                if(R > m)modify(x,L,R,rs);
                push_up(v);            
            }    
        }
        
        node query(int L,int R,int l = 1, int r = n,int v = 1){
            if(l >= L && r <= R)
                return Tree[v];
            else {
                if(Tree[v].lazy) push_down(l,r,v);
                int m = (l + r) / 2;
                node ans;
                ans.vmin = oo, ans.vmax = -oo, ans.sum = 0;
                if(L <= m){
                    node nw = query(L,R,ls);
                    ans.vmin = min(ans.vmin, nw.vmin);
                    ans.vmax = max(ans.vmax, nw.vmax);
                    ans.sum += nw.sum;
                }
                if(R > m){
                    node nw = query(L,R,rs);
                    ans.vmin = min(ans.vmin, nw.vmin);
                    ans.vmax = max(ans.vmax, nw.vmax);
                    ans.sum += nw.sum;
                }
                return ans;
            }
        }
    };
    
    SegTree Tr;
    int main(){
        freopen("redpacket.in","r",stdin);
        freopen("redpacket.out","w",stdout);
        cin>>n;
        for(int i = 1; i < n; i++){
            int u,v;
            scanf("%d%d",&u,&v);
            adde(u,v);
            adde(v,u);
        }
            
        dep[1] = 1;
        dfs(1,1);
    //    Tr.build();
        cin>>m;
        for(int i = 1; i <= m; i++){
            string opt;
            cin>>opt;
            if(opt[0] == 'a'){
                int u;
                scanf("%d",&u);
                SegTree::node nw;
                nw = Tr.query(in[u],out[u]);
                cout<<nw.sum<<endl;
            }
            else if(opt[0] == 'g'){
                int u, x;
                scanf("%d%d",&u,&x);
                Tr.    modify(x,in[u],out[u]);
            }
            else {
                int u;
                scanf("%d",&u);
                SegTree::node nw;
                nw = Tr.query(in[u],in[u]);
                cout<<nw.sum<<endl;
            }
        }
    }

    第三题:比如这条红链上+5,在两个节点上+5,他们的LCA(root)-5,父节点也-5,单点query时就查子树和就好了

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 100005, P = 20;
    int in[maxn], f[maxn], head[2 * maxn],to[2 * maxn],last[2 *maxn],co[2 * maxn];
    int idx, anc[maxn][P+1], dep[maxn], out[maxn], seq[maxn], idx1;
    vector <int> G[maxn];
    int n,m;
    void dfs(int u,int from){
        in[u] = ++idx;
        
        anc[u][0] = from;
        //fprintf(stderr, "from = %d  u = %d
    ",from, u);
        for(int p = 1; p <= P; p++) {
        //    fprintf(stderr, "p = %d anc[%d][%d] = %d
    ", p, u, p, anc[u][p]);
            anc[u][p] = anc[anc[u][p-1]][p-1];
        }
        for(int i = head[u]; i; i = last[i]){
            int v = to[i];
            if(v != from){
                dep[v] = dep[u] + 1;
                f[v] = u;
                dfs(v,u);
            }
        }    
        out[u] = idx;
    }
    int lca(int u,int v){//倍增求LCA
        if(dep[u] < dep[v])swap(u, v);
        int t = dep[u] - dep[v];
        for(int p = 0; t; t >>= 1, p++)
            if(t & 1)u = anc[u][p];
        if(u == v)return v;
        
        for(int p = P; p >=0; p--)
            if(anc[u][p] != anc[v][p])
                u = anc[u][p], v = anc[v][p];
        return anc[u][0];
    }
    int query(int x){
        int ret = 0;
        while(x > 0){
            ret += seq[x];
            x -= (x & -x);
        }
        return ret;
    }
    
    void issum(int x,int val){
        while(x <= n){
            seq[x] += val;
            x += (x & -x);
        }
    }
    void adde(int u,int v){
        idx1++;
        last[idx1] = head[u];
        to[idx1] = v;    
        head[u] = idx1;
    }
    int main(){
        freopen("redpacket2.in","r",stdin);
        freopen("redpacket2.out","w",stdout);
        //ios::sync_with_stdio(false);
        cin>>n;
        for(int i = 1; i < n; i++){
            int u,v;
            scanf("%d%d",&u,&v);
            adde(u,v);
            adde(v,u);
        }
        f[1] = 0;
        dep[1] = 1;
        dfs(1,1);    
        cin>>m;
        for(int i = 1;i <= m; i++){
            string opt;
            cin>>opt;
            if(opt[0] == 's'){
                int u;
                scanf("%d",&u);
                printf("%d
    ",query(out[u])-query(in[u]-1));
            }
            else{
                int u,v,val;
                scanf("%d%d%d",&u,&v,&val);
                issum(in[u],val);
                issum(in[v],val);
                int q = lca(u, v);
                issum(in[q],-val);
                int  p = f[q];
                if(p != 0)
                issum(in[p],-val);
            }
        }
    }
  • 相关阅读:
    bzoj 5092: [Lydsy1711月赛]分割序列
    bzoj1173: [Balkan2007]Point
    bzoj1536: [POI2005]Akc- Special Forces Manoeuvres
    bzoj2178: 圆的面积并
    bzoj1043 下落的圆盘
    bzoj2674 Attack
    bzoj1201: [HNOI2005]数三角形
    bzoj3135: [Baltic2013]pipesd
    bzoj1760 [Baltic2009]Triangulation
    bzoj3136
  • 原文地址:https://www.cnblogs.com/EdSheeran/p/8428184.html
Copyright © 2011-2022 走看看