树链剖分+线段树 POJ3237 权值在边 模板

来源:互联网 发布:公司屏蔽了淘宝怎么办 编辑:程序博客网 时间:2024/05/18 04:00
#include<stdio.h>#include<string.h>#include<stdlib.h>#include<iostream>#include<algorithm>#include<vector>#include<queue>#include<map>#include<math.h>using namespace std;const int maxn=100010;struct Edge{     int to;     int next;}edge[maxn*2];int head[maxn],tot;int top[maxn];//top[v]表示v所在的重链的顶端节点int fa[maxn];//父亲节点int deep[maxn];//深度int num[maxn];//num[v]表示以v为根的子树的节点数int p[maxn];//p[v]表示v与其父亲节点的连边在线段树中的位置int fp[maxn];//和p数组相反int son[maxn];//重儿子int pos;int e[maxn][3];void init(){     tot=0;     memset(head,-1,sizeof(head));     pos=0;     memset(son,-1,sizeof(son));}void add(int u,int v){     edge[tot].to=v;     edge[tot].next=head[u];     head[u]=tot++;}void dfs1(int u,int father,int dep)//第一遍dfs求出fa,deep,num,son{     deep[u]=dep;     fa[u]=father;     num[u]=1;     for(int i=head[u];i!=-1;i=edge[i].next)     {          int v=edge[i].to;          if(v!=father)          {               dfs1(v,u,dep+1);               num[u]+=num[v];               if(son[u]==-1||num[son[u]]<num[v])                    son[u]=v;          }     }}void dfs2(int u,int tp)//第二遍dfs求出top和p{     top[u]=tp;     p[u]=pos++;     fp[p[u]]=u;     if(son[u]==-1)          return;     dfs2(son[u],tp);     for(int i=head[u];i!=-1;i=edge[i].next)     {          int v=edge[i].to;          if(v!=fa[u]&&v!=son[u])               dfs2(v,v);     }}struct node{     int l,r,maxx,minn,nege;}q[maxn*3];void build(int i,int l,int r){     q[i].l=l;     q[i].r=r;     q[i].maxx=q[i].minn=q[i].nege=0;     if(l==r)          return;     int mid=(l+r)/2;     build(i*2,l,mid);     build(i*2+1,mid+1,r);}void pushup(int i){     q[i].maxx=max(q[i*2].maxx,q[i*2+1].maxx);     q[i].minn=min(q[i*2].minn,q[i*2+1].minn);}void pushdown(int i){     if(q[i].l==q[i].r)          return;     if(q[i].nege)     {          q[i*2].maxx=-q[i*2].maxx;          q[i*2].minn=-q[i*2].minn;          swap(q[i*2].maxx,q[i*2].minn);          q[i*2+1].maxx=-q[i*2+1].maxx;          q[i*2+1].minn=-q[i*2+1].minn;          swap(q[i*2+1].maxx,q[i*2+1].minn);          q[i*2].nege^=1;          q[i*2+1].nege^=1;          q[i].nege=0;     }}void update(int i,int k,int val)// 更新线段树的第k个值为val{     if(q[i].l==k&&q[i].r==k)     {          q[i].maxx=val;          q[i].minn=val;          q[i].nege=0;          return;     }     pushdown(i);     int mid=(q[i].l+q[i].r)/2;     if(k<=mid)          update(i*2,k,val);     else          update(i*2+1,k,val);     pushup(i);}int query(int i,int l,int r)//查询线段树中[l,r] 的最大值{     if(q[i].l==l&&q[i].r==r)     {          return q[i].maxx;     }     pushdown(i);     int mid=(q[i].l+q[i].r)/2;     if(r<=mid)          return query(i*2,l,r);     else if(l>mid)          return query(i*2+1,l,r);     else     {          return max(query(i*2,l,mid),query(i*2+1,mid+1,r));     }     pushup(i);}int findmax(int u,int v)//查询u->v边的最大值{     int f1=top[u];     int f2=top[v];     int tmp=-100000000;     while(f1!=f2)     {          if(deep[f1]<deep[f2])          {               swap(f1,f2);               swap(u,v);          }          tmp=max(tmp,query(1,p[f1],p[u]));          u=fa[f1];          f1=top[u];     }     if(u==v)          return tmp;     if(deep[u]>deep[v])          swap(u,v);     return max(tmp,query(1,p[son[u]],p[v]));}void Negate1(int i,int l,int r)// 更新线段树的区间[l,r]取反{     if(q[i].l==l&&q[i].r==r)     {          q[i].maxx=-q[i].maxx;          q[i].minn=-q[i].minn;          swap(q[i].maxx,q[i].minn);          q[i].nege^=1;          return;     }     pushdown(i);     int mid=(q[i].l+q[i].r)/2;     if(r<=mid)          Negate1(i*2,l,r);     else if(l>mid)          Negate1(i*2+1,l,r);     else     {          Negate1(i*2,l,mid);          Negate1(i*2+1,mid+1,r);     }     pushup(i);}void Negate(int u,int v)//把u-v路径上的边的值都设置为val{     int f1=top[u];     int f2=top[v];     while(f1!=f2)     {          if(deep[f1]<deep[f2])          {               swap(f1,f2);               swap(u,v);          }          Negate1(1,p[f1],p[u]);          u=fa[f1];          f1=top[u];     }     if(u==v)          return;     if(deep[u]>deep[v])          swap(u,v);     return Negate1(1,p[son[u]],p[v]);}int main(void){     int i,j,k,t,n;     scanf("%d",&t);     while(t--)     {          init();          scanf("%d",&n);          for(i=0;i<n-1;i++)          {               scanf("%d%d%d",&e[i][0],&e[i][1],&e[i][2]);               add(e[i][0],e[i][1]);               add(e[i][1],e[i][0]);          }          dfs1(1,0,0);          dfs2(1,1);          build(1,0,pos-1);          for(i=0;i<n-1;i++)          {               if(deep[e[i][0]]>deep[e[i][1]])                    swap(e[i][0],e[i][1]);               update(1,p[e[i][1]],e[i][2]);          }          char op[10];          int x,y;          while(scanf("%s",op)!=EOF)          {               if(op[0]=='D')                    break;               scanf("%d%d",&x,&y);               if(op[0]=='Q')                    printf("%d\n",findmax(x,y));//查询x->y路径上边权的最大值               else if(op[0]=='C')                    update(1,p[e[x-1][1]],y);//改变第x条边的值为y               else                    Negate(x,y);          }     }     return 0;}