BZOJ 2157 旅游 树链剖分

来源:互联网 发布:88端口怎么起 编辑:程序博客网 时间:2024/05/03 02:00

题目大意:给出一棵树,支持以下操作:1.改变一条边的边权。2.将x到y路径的权值取反。3.查询x到y路径上最大值,最小值和权值和。


思路:好裸的链剖水题啊,唯一麻烦一点地是权值放在了边上,注意一下处理就没问题了。。


CODE:


#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define MAX 40010#define INF 0x3f3f3f3fusing namespace std;#define LEFT (pos << 1)#define RIGHT (pos << 1|1)#define min(a,b) ((a) < (b) ? (a):(b))#define max(a,b) ((a) > (b) ? (a):(b)) int points,asks;int head[MAX],total;int _next[MAX << 1],aim[MAX << 1]; struct Edge{    int x,y,len;    int pos;     Edge(int _,int __,int ___):x(_),y(__),len(___) {}    Edge() {}}edge[MAX]; inline void Add(int x,int y){    _next[++total] = head[x];    aim[total] = y;    head[x] = total;} int father[MAX],deep[MAX],son[MAX],size[MAX]; void _DFS(int x,int last){    father[x] = last;    deep[x] = deep[last] + 1;    size[x] = 1;    int max_size = 0;    for(int i = head[x]; i; i = _next[i]) {        if(aim[i] == last)  continue;        _DFS(aim[i],x);        size[x] += size[aim[i]];        if(size[aim[i]] > max_size)            max_size = size[aim[i]],son[x] = aim[i];    }} int pos[MAX],top[MAX],cnt; void DFS(int x,int last,int _top){    pos[x] = ++cnt;    top[x] = _top;    if(son[x])  DFS(son[x],x,_top);    for(int i = head[x]; i; i = _next[i]) {        if(aim[i] == last || aim[i] == son[x])  continue;        DFS(aim[i],x,aim[i]);    }} struct SegTree{    int sum,_min,_max;    bool inv;     SegTree(int _ = 0,int __ = INF,int ___ = -INF):sum(_),_min(__),_max(___) {}    void Inv() {        inv ^= 1;        sum *= -1;        int t = _max;        _max = -_min;        _min = -t;    }}tree[MAX << 2]; inline void PushUp(int pos){    tree[pos].sum = tree[LEFT].sum + tree[RIGHT].sum;    tree[pos]._min = min(tree[LEFT]._min,tree[RIGHT]._min);    tree[pos]._max = max(tree[LEFT]._max,tree[RIGHT]._max);} inline SegTree PushUp(SegTree a,SegTree b){    SegTree re;    re.sum = a.sum + b.sum;    re._min = min(a._min,b._min);    re._max = max(a._max,b._max);    return re;} inline void PushDown(int pos){    if(tree[pos].inv) {        tree[LEFT].Inv();        tree[RIGHT].Inv();        tree[pos].inv = false;    }} void Modify(int l,int r,int x,int pos,int c){    if(l == r) {        tree[pos].sum = tree[pos]._min = tree[pos]._max = c;        return ;    }    PushDown(pos);    int mid = (l + r) >> 1;    if(x <= mid) Modify(l,mid,x,LEFT,c);    else    Modify(mid + 1,r,x,RIGHT,c);    PushUp(pos);} void Change(int l,int r,int x,int y,int pos){    if(l == x && r == y) {        tree[pos].Inv();        return ;    }    PushDown(pos);    int mid = (l + r) >> 1;    if(y <= mid) Change(l,mid,x,y,LEFT);    else if(x > mid) Change(mid + 1,r,x,y,RIGHT);    else {        Change(l,mid,x,mid,LEFT);        Change(mid + 1,r,mid + 1,y,RIGHT);    }    PushUp(pos);} inline void Change(int x,int y){    while(top[x] != top[y]) {        if(deep[top[x]] < deep[top[y]])            swap(x,y);        Change(1,points,pos[top[x]],pos[x],1);        x = father[top[x]];    }    if(x == y)  return ;    if(deep[x] < deep[y])    swap(x,y);    Change(1,points,pos[y] + 1,pos[x],1);} SegTree Ask(int l,int r,int x,int y,int pos){    if(l == x && r == y)    return tree[pos];    PushDown(pos);    int mid = (l + r) >> 1;    if(y <= mid) return Ask(l,mid,x,y,LEFT);    if(x > mid)      return Ask(mid + 1,r,x,y,RIGHT);    SegTree left = Ask(l,mid,x,mid,LEFT);    SegTree right = Ask(mid + 1,r,mid + 1,y,RIGHT);    return PushUp(left,right);} inline SegTree Ask(int x,int y){    SegTree re(0,INF,-INF);    while(top[x] != top[y]) {        if(deep[top[x]] < deep[top[y]])            swap(x,y);        re = PushUp(re,Ask(1,points,pos[top[x]],pos[x],1));        x = father[top[x]];     }    if(x == y)  return re;    if(deep[x] < deep[y])    swap(x,y);    re = PushUp(re,Ask(1,points,pos[y] + 1,pos[x],1));    return re;} char c[10]; int main(){    cin >> points;    for(int x,y,z,i = 1; i < points; ++i) {        scanf("%d%d%d",&x,&y,&z);        x++,y++;        Add(x,y),Add(y,x);        edge[i] = Edge(x,y,z);    }    _DFS(1,0);    DFS(1,0,1);    for(int i = 1; i < points; ++i) {        edge[i].pos = deep[edge[i].x] > deep[edge[i].y] ? pos[edge[i].x]:pos[edge[i].y];        Modify(1,points,edge[i].pos,1,edge[i].len);    }    cin >> asks;    for(int x,y,i = 1; i <= asks; ++i) {        scanf("%s%d%d",c,&x,&y);        if(c[0] == 'C') Modify(1,points,edge[x].pos,1,y);        else if(c[0] == 'N')    Change(x + 1,y + 1);        else {            SegTree ans = Ask(x + 1,y + 1);            if(c[0] == 'S')         printf("%d\n",ans.sum);            else if(c[1] == 'I')    printf("%d\n",ans._min);            else                    printf("%d\n",ans._max);        }    }    return 0;}


0 0