zoukankan      html  css  js  c++  java
  • BZOJ 2157 旅行(树链剖分码农题)

    写了5KB,1发AC。。。

    题意:给出一颗树,支持5种操作。

    1.修改某条边的权值。2.将u到v的经过的边的权值取负。3.求u到v的经过的边的权值总和。4.求u到v的经过的边的权值最大值。5.求u到v经过的边的权值最小值。

    基于边权的树链剖分,放在线段树上变成了区间维护问题了,线段树维护4个量min,max,sum,tag就可以了。

    # include <cstdio>
    # include <cstring>
    # include <cstdlib>
    # include <iostream>
    # include <vector>
    # include <queue>
    # include <stack>
    # include <map>
    # include <bitset>
    # include <set>
    # include <cmath>
    # include <algorithm>
    using namespace std;
    # define lowbit(x) ((x)&(-x))
    # define pi acos(-1.0)
    # define eps 1e-8
    # define MOD 30031
    # define INF 1000000000
    # define mem(a,b) memset(a,b,sizeof(a))
    # define FOR(i,a,n) for(int i=a; i<=n; ++i)
    # define FO(i,a,n) for(int i=a; i<n; ++i)
    # define bug puts("H");
    # define lch p<<1,l,mid
    # define rch p<<1|1,mid+1,r
    # define mp make_pair
    # define pb push_back
    typedef pair<int,int> PII;
    typedef vector<int> VI;
    # pragma comment(linker, "/STACK:1024000000,1024000000")
    typedef long long LL;
    int Scan() {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    const int N=20005;
    //Code begin...
    
    struct Edge{int p, next;}edge[N<<1];
    struct Seg{int sum, ma, mi;}seg[N<<3];
    bool tag[N<<3];
    int head[N], cnt=1, E[N][3], n;
    int top[N], fa[N], deep[N], num[N], p[N], fp[N], son[N], pos;
    
    void add_edge(int u, int v){
        edge[cnt].p=v; edge[cnt].next=head[u]; head[u]=cnt++;
    }
    void init(){mem(son,-1); pos=1;}
    void dfs1(int u, int pre, int d){
        deep[u]=d; fa[u]=pre; num[u]=1;
        for (int i=head[u]; i; i=edge[i].next) {
            int v=edge[i].p;
            if (v==pre) continue;
            dfs1(v,u,d+1); num[u]+=num[v];
            if (son[u]==-1||num[v]>num[son[u]]) son[u]=v;
        }
    }
    void getpos(int u, int sp){
        top[u]=sp; p[u]=pos++; fp[p[u]]=u;
        if (son[u]==-1) return ;
        getpos(son[u],sp);
        for (int i=head[u]; i; i=edge[i].next) {
            int v=edge[i].p;
            if (v!=son[u]&&v!=fa[u]) getpos(v,v);
        }
    }
    void push_up(int p){
        seg[p].sum=seg[p<<1].sum+seg[p<<1|1].sum;
        seg[p].ma=max(seg[p<<1].ma,seg[p<<1|1].ma);
        seg[p].mi=min(seg[p<<1].mi,seg[p<<1|1].mi);
    }
    void push_down(int p){
        if (!tag[p]) return ;
        seg[p].sum=-seg[p].sum; swap(seg[p].ma,seg[p].mi); seg[p].ma=-seg[p].ma; seg[p].mi=-seg[p].mi;
        tag[p<<1]^=tag[p]; tag[p<<1|1]^=tag[p]; tag[p]=false;
    }
    void Update(int p, int l, int r, int L, int val){
        push_down(p);
        if (L>r||L<l) return ;
        if (L==l&&L==r) seg[p].ma=seg[p].mi=seg[p].sum=val;
        else {
            int mid=(l+r)>>1;
            Update(lch,L,val); Update(rch,L,val); push_up(p);
        }
    }
    void Inv(int p, int l, int r, int L, int R){
        push_down(p);
        if (L>r||R<l) return ;
        if (L<=l&&R>=r) tag[p]^=1, push_down(p);
        else {
            int mid=(l+r)>>1;
            Inv(lch,L,R); Inv(rch,L,R); push_up(p);
        }
    }
    int Query_Max(int p, int l, int r, int L, int R){
        push_down(p);
        if (L>r||R<l) return -INF;
        if (L<=l&&R>=r) return seg[p].ma;
        int mid=(l+r)>>1;
        return max(Query_Max(lch,L,R),Query_Max(rch,L,R));
    }
    int Query_Min(int p, int l, int r, int L, int R){
        push_down(p);
        if (L>r||R<l) return INF;
        if (L<=l&&R>=r) return seg[p].mi;
        int mid=(l+r)>>1;
        return min(Query_Min(lch,L,R),Query_Min(rch,L,R));
    }
    int Query_Sum(int p, int l, int r, int L, int R){
        push_down(p);
        if (L>r||R<l) return 0;
        if (L<=l&&R>=r) return seg[p].sum;
        int mid=(l+r)>>1;
        return Query_Sum(lch,L,R)+Query_Sum(rch,L,R);
    }
    int Sol(int u, int v, int flag){
        int f1=top[u], f2=top[v], ans;
        if (flag==2) ans=0;
        else if (flag==3) ans=-INF;
        else ans=INF;
        while (f1!=f2) {
            if (deep[f1]<deep[f2]) swap(f1,f2), swap(u,v);
            if (flag==1) Inv(1,1,n,p[f1],p[u]);
            else if (flag==2) ans+=Query_Sum(1,1,n,p[f1],p[u]);
            else if (flag==3) ans=max(ans,Query_Max(1,1,n,p[f1],p[u]));
            else  ans=min(ans,Query_Min(1,1,n,p[f1],p[u]));
            u=fa[f1]; f1=top[u];
        }
        if (u==v) return ans;
        if (deep[u]>deep[v]) swap(u,v);
        if (flag==1) {Inv(1,1,n,p[son[u]],p[v]); return 0;}
        else if (flag==2) return ans+Query_Sum(1,1,n,p[son[u]],p[v]);
        else if (flag==3) return max(ans,Query_Max(1,1,n,p[son[u]],p[v]));
        else return min(ans,Query_Min(1,1,n,p[son[u]],p[v]));
    }
    int main ()
    {
        int m, x, y;
        char s[5];
        scanf("%d",&n); init();
        FO(i,1,n) scanf("%d%d%d",&E[i][0],&E[i][1],&E[i][2]), ++E[i][0], ++E[i][1], add_edge(E[i][0],E[i][1]), add_edge(E[i][1],E[i][0]);
        dfs1(1,0,0); getpos(1,1);
        FO(i,1,n) {
            if (deep[E[i][0]]>deep[E[i][1]]) swap(E[i][0],E[i][1]);
            Update(1,1,n,p[E[i][1]],E[i][2]);
        }
        scanf("%d",&m);
        while (m--) {
            scanf("%s%d%d",s,&x,&y);
            if (!strcmp(s,"C")) Update(1,1,n,p[E[x][1]],y);
            else if (!strcmp(s,"N")) ++x, ++y, Sol(x,y,1);
            else if (!strcmp(s,"SUM")) ++x, ++y, printf("%d
    ",Sol(x,y,2));
            else if (!strcmp(s,"MAX")) ++x, ++y, printf("%d
    ",Sol(x,y,3));
            else ++x, ++y, printf("%d
    ",Sol(x,y,4));
        }
        return 0;
    }
    View Code
  • 相关阅读:
    指针
    初级程序员面试不靠谱指南(七)
    初级程序员面试不靠谱指南(六)
    Hadoop 中利用 mapreduce 读写 mysql 数据
    Mapreduce的文件和hbase共同输入
    mapreduce多文件输出的两方法
    mapreduce中一个map多个输入路径
    GDB介绍
    超强的指针学习笔记
    iOS开发之Appstore篇——版本更新
  • 原文地址:https://www.cnblogs.com/lishiyao/p/6886606.html
Copyright © 2011-2022 走看看