BZOJ 2157 旅行(树链剖分码农题)

Posted freeloop

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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\n",Sol(x,y,2));
        else if (!strcmp(s,"MAX")) ++x, ++y, printf("%d\n",Sol(x,y,3));
        else ++x, ++y, printf("%d\n",Sol(x,y,4));
    }
    return 0;
}
View Code

 

以上是关于BZOJ 2157 旅行(树链剖分码农题)的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 2157 旅游(树链剖分+线段树)

bzoj 2157: 旅游树链剖分+线段树

BZOJ 2157 「国家集训队」旅游(树链剖分,线段树,边权转点权)BZOJ计划

BZOJ 2157 「国家集训队」旅游(树链剖分,线段树,边权转点权)BZOJ计划

bzoj 3531 [Sdoi2014]旅行(树链剖分,线段树)

BZOJ 3531SDOI 2014旅行 树链剖分