poj 3237 加强版 query on a tree 树链剖分

来源:互联网 发布:怎样打开Windows目录 编辑:程序博客网 时间:2024/06/01 08:03

链接:

http://www.spoj.pl/problems/QTREE/

http://poj.org/problem?id=3237


题意:一棵树,两种更新操作,改变一条边的边权,将a ->b路径上的所有边权取反,询问一条路径上的最大边权

都是典型的树链剖分,下面一题是上面的加强版,还要在树上进行成段更新,其实也不难。

只是区间还要再记录一个最小值,因为取反操作的话会使得区间的最大值和最小值互换。

然后就是树链剖分的老套路,如果是重链,在线段树中更新,否则直接改变边权。

线段树中下放懒惰标记的时候写漏了,调了许久,囧爆了。。。。

好像还可以用动态树实现吧,概念都看懂了,只是没实践过,改天去学了再贴上来吧

下面是这两题的代码,我的代码有点搓 - -,观看请慎重,以免伤了眼*_*

spoj  375  query on a tree

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1const int maxn = 20010;const int inf = ~0u>>2;int M[maxn<<2];struct node{    int s,t,w,next;}edge[maxn*2];int E,n;int size[maxn] , fa[maxn] , heavy[maxn] , head[maxn] , dep[maxn] , rev[maxn] , num[maxn] , cost[maxn];int Seg_size;inline void Max(int &x,int y){if(x<y) x=y;}int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}void add_edge(int s,int t,int w){    edge[E].w=w;    edge[E].s=s;    edge[E].t=t;    edge[E].next=head[s];    head[s]=E++;}void dfs(int u,int f){    int mx=-1,e=-1;    size[u]=1;    for(int i=head[u];i!=-1;i=edge[i].next)    {        int v=edge[i].t;        if(v==f) continue;        dep[v]=dep[u]+1;        rev[v]=i^1;        dfs(v,u);        size[u]+=size[v];        if(size[v]>mx)        {            mx=size[v];            e=i;        }    }    heavy[u]=e;    if(e!=-1)  fa[edge[e].t]=u;}inline void pushup(int rt){    M[rt]=max(M[rt<<1],M[rt<<1|1]);}void build(int l,int r,int rt){    M[rt]=inf;    if(l==r){        return ;    }    int m=(l+r)>>1;    build(lson);    build(rson);}void update(int p,int val,int l,int r,int rt){    if(l==r){       M[rt]=val;       return ;    }    int m=(l+r)>>1;    if(p<=m) update(p,val,lson);    else update(p,val,rson);    pushup(rt);}int query(int L,int R,int l,int r,int rt){    if(L<=l&&r<=R){        return M[rt];    }    int m=(l+r)>>1;    int ret=0;    if(L<=m) ret=max(ret,query(L,R,lson));    if(R>m) ret=max(ret,query(L,R,rson));    return ret;}void prepare(){    build(1,n-1,1);    memset(num,-1,sizeof(num));    dep[0]=0;Seg_size=0;    for(int i=0;i<n;i++) fa[i]=i;    dfs(0,0);        for(int i=0;i<n;i++)    {        if(heavy[i]==-1)        {            int pos=i;            while(pos && edge[heavy[edge[rev[pos]].t]].t == pos)            {                int t=rev[pos];                num[t]=num[t^1]=++Seg_size;                update(Seg_size,edge[t].w,1,n-1,1);                pos=edge[t].t;            }        }    }}void change(int edge_id,int val){    if(num[edge_id]==-1) edge[edge_id].w=edge[edge_id^1].w=val;    else update(num[edge_id],val,1,n-1,1);}int calc(int u,int lca){    int ans=-inf;int vi=0;    while(u!=lca)    {        vi++;        if(vi==10) break;        int r=rev[u];        if(num[r]==-1) Max(ans,edge[r].w),u=edge[r].t;        else         {            int p=fa[u];            if(dep[p] < dep[lca]) p=lca;            int l=num[r];            int r=num[heavy[p]];            Max(ans,query(l,r,1,n-1,1));            u=p;        }    }    return ans;}int lca(int u,int v){    while(1)    {        int a=find(u),b=find(v);        if(a==b) return dep[u] < dep[v] ? u : v;//a,b在同一条重链上        else if(dep[a]>=dep[b]) u=edge[rev[a]].t;        else v=edge[rev[b]].t;    }}int solve(int u,int v){    int p=lca(u,v);    return max(calc(u,p),calc(v,p));}int main(){    int t,i,a,b,c;    scanf("%d",&t);    while(t--)    {        memset(head,-1,sizeof(head));        E=0;        scanf("%d",&n);        for(i=0;i<n-1;i++)        {            scanf("%d%d%d",&a,&b,&c);a--;b--;            add_edge(a,b,c);            add_edge(b,a,c);        }        prepare();        char op[20];        while(scanf("%s",op)!=EOF && strcmp(op,"DONE"))        {            if(op[0]=='C')            {                scanf("%d%d",&a,&c);                change((a-1)*2,c);            }            else             {                scanf("%d%d",&a,&b);                printf("%d\n",solve(a-1,b-1));            }        }    }    return 0;}/*131 2 12 3 2QUERY 1 2CHANGE 1 3QUERY 1 2DONE13171 2 11 3 22 4 32 5 43 6 53 7 6Query 1 7*/



poj 3237

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1const int maxn = 100010;const int inf = ~0u>>2;int M[maxn<<2];int Mi[maxn<<2];int col[maxn<<2];struct node{int s,t,w,next;}edge[maxn*2];int E,n;int size[maxn] , fa[maxn] , heavy[maxn] , head[maxn] , dep[maxn] , rev[maxn] , num[maxn] , cost[maxn];int Seg_size;inline void Max(int &x,int y){if(x<y) x=y;}inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a>b?b:a;}int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}void add_edge(int s,int t,int w){edge[E].w=w;edge[E].s=s;edge[E].t=t;edge[E].next=head[s];head[s]=E++;}void dfs(int u,int f){int mx=-1,e=-1;size[u]=1;for(int i=head[u];i!=-1;i=edge[i].next){int v=edge[i].t;if(v==f) continue;dep[v]=dep[u]+1;rev[v]=i^1;dfs(v,u);size[u]+=size[v];if(size[v]>mx){mx=size[v];e=i;}}heavy[u]=e;if(e!=-1)  fa[edge[e].t]=u;}void build(int l,int r,int rt){Mi[rt]=inf;M[rt]=-inf;col[rt]=0;if(l==r){return ;}int m=(l+r)>>1;build(lson);build(rson);}inline void pushup(int rt){M[rt]=max(M[rt<<1],M[rt<<1|1]);Mi[rt]=min(Mi[rt<<1],Mi[rt<<1|1]);}void make(int rt){int tmp=Mi[rt];Mi[rt]=-M[rt];M[rt]=-tmp;}void pushdown(int rt){if(col[rt]){       col[rt<<1]^=1;   make(rt<<1);   col[rt<<1|1]^=1;   make(rt<<1|1);   col[rt]=0;//很久没写线段树,连这个都忘了,囧}}void update(int p,int val,int l,int r,int rt){if(l==r){   Mi[rt]=M[rt]=val;   return ;}pushdown(rt);int m=(l+r)>>1;if(p<=m) update(p,val,lson);else update(p,val,rson);pushup(rt);}void justdoit(int L,int R,int l,int r,int rt){//printf("L=%d R=%d l=%d r=%d\n",L,R,l,r);if(L<=l&&r<=R){col[rt]^=1;make(rt);return ;}pushdown(rt);int m=(l+r)>>1;if(L<=m) justdoit(L,R,lson);if(R>m) justdoit(L,R,rson);pushup(rt);}int query(int L,int R,int l,int r,int rt){if(L<=l&&r<=R){return M[rt];}pushdown(rt);int m=(l+r)>>1;int ret=-inf;if(L<=m) ret=max(ret,query(L,R,lson));if(R>m) ret=max(ret,query(L,R,rson));return ret;}void prepare(){build(1,n-1,1);memset(num,-1,sizeof(num));dep[0]=0;Seg_size=0;for(int i=0;i<n;i++) fa[i]=i;dfs(0,0);for(int i=0;i<n;i++){if(heavy[i]==-1){int pos=i;while(pos && edge[heavy[edge[rev[pos]].t]].t == pos){int t=rev[pos];num[t]=num[t^1]=++Seg_size;update(Seg_size,edge[t].w,1,n-1,1);pos=edge[t].t;}}}}void change(int edge_id,int val){if(num[edge_id]==-1) edge[edge_id].w=edge[edge_id^1].w=val;else update(num[edge_id],val,1,n-1,1);}int calc(int u,int lca){int ans=-inf;    while(u!=lca){int r=rev[u];if(num[r]==-1) Max(ans,edge[r].w),u=edge[r].t;else {int p=fa[u];if(dep[p] < dep[lca]) p=lca;int l=num[r];int r=num[heavy[p]];Max(ans,query(l,r,1,n-1,1));u=p;}}return ans;}void gao(int u,int lca){while(u!=lca){int r=rev[u];if(num[r]==-1) edge[r].w=edge[r^1].w=-edge[r].w,u=edge[r].t;else{int p=fa[u];if(dep[p] < dep[lca]) p=lca;int l=num[r];int r=num[heavy[p]];//printf("l=%d r=%d\n",l,r);justdoit(l,r,1,n-1,1);u=p;}}}int lca(int u,int v){while(1){int a=find(u),b=find(v);if(a==b) return dep[u] < dep[v] ? u : v;//a,b在同一条重链上else if(dep[a]>=dep[b]) u=edge[rev[a]].t;else v=edge[rev[b]].t;}}int solve(int u,int v){int p=lca(u,v);return max(calc(u,p),calc(v,p));}void sol(int u,int v){int p=lca(u,v);//printf("p=%d\n",p);gao(u,p);gao(v,p);}int main(){int t,i,a,b,c;scanf("%d",&t);while(t--){memset(head,-1,sizeof(head));E=0;scanf("%d",&n);for(i=0;i<n-1;i++){scanf("%d%d%d",&a,&b,&c);a--;b--;add_edge(a,b,c);add_edge(b,a,c);}prepare();char op[20];while(scanf("%s",op)!=EOF && strcmp(op,"DONE")){if(op[0]=='C'){scanf("%d%d",&a,&c);change((a-1)*2,c);}else if(op[0]=='N'){scanf("%d%d",&a,&b);if(a==b) while(1);sol(a-1,b-1);}else {scanf("%d%d",&a,&b);if(a==b) while(1);printf("%d\n",solve(a-1,b-1));}}}return 0;}



原创粉丝点击