zoukankan      html  css  js  c++  java
  • 树链剖分||dfs序 各种题

    1.【bzoj4034】[HAOI2015]T2

    有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个

    操作,分为三种:
    操作 1 :把某个节点 x 的点权增加 a 。
    操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
    操作 3 :询问某个节点 x 到根的路径中所有点的点权和。
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define ll long long
    #define inf 1000000000
    #define mod 1000000000
    using namespace std;
    int read()
    {
        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;
    }
    int n,m,cnt;
    int last[100005];
    int id,pos[100005],mx[100005],v[100005];
    int bl[100005],size[100005],fa[100005];
    ll tag[400005],sum[400005];
    struct edge{
        int to,next;
    }e[200005];
    void insert(int u,int v)
    {
        e[++cnt]=(edge){v,last[u]};last[u]=cnt;
        e[++cnt]=(edge){u,last[v]};last[v]=cnt;
    }
    void dfs(int x)
    {
        size[x]=1;
        for(int i=last[x];i;i=e[i].next)
            if(e[i].to!=fa[x])
            {
                fa[e[i].to]=x;
                dfs(e[i].to);
                size[x]+=size[e[i].to];
                mx[x]=max(mx[x],mx[e[i].to]);
            }
    }
    void dfs2(int x,int cha)
    {
        bl[x]=cha;pos[x]=mx[x]=++id;
        int k=0;
        for(int i=last[x];i;i=e[i].next)
            if(e[i].to!=fa[x]&&size[e[i].to]>size[k])
                k=e[i].to;
        if(k)
        {
            dfs2(k,cha);mx[x]=max(mx[x],mx[k]);
        }
        for(int i=last[x];i;i=e[i].next)
            if(e[i].to!=fa[x]&&e[i].to!=k)
            {
                dfs2(e[i].to,e[i].to);
                mx[x]=max(mx[x],mx[e[i].to]);
            }
    }
    void pushdown(int l,int r,int k)
    {
        if(l==r)return;
        int mid=(l+r)>>1;ll t=tag[k];tag[k]=0;
        tag[k<<1]+=t;tag[k<<1|1]+=t;
        sum[k<<1]+=t*(mid-l+1);
        sum[k<<1|1]+=t*(r-mid);
    }
    void add(int k,int l,int r,int x,int y,ll val)
    {
        if(tag[k])pushdown(l,r,k);
        if(l==x&&y==r){tag[k]+=val;sum[k]+=(r-l+1)*val;return;}
        int mid=(l+r)>>1;
        if(x<=mid)add(k<<1,l,mid,x,min(mid,y),val);
        if(y>=mid+1)add(k<<1|1,mid+1,r,max(mid+1,x),y,val);
        sum[k]=sum[k<<1]+sum[k<<1|1];
    }
    ll query(int k,int l,int r,int x,int y)
    {
        if(tag[k])pushdown(l,r,k);
        if(l==x&&y==r)return sum[k];
        int mid=(l+r)>>1;
        ll ans=0;
        if(x<=mid)
            ans+=query(k<<1,l,mid,x,min(mid,y));
        if(y>=mid+1)
            ans+=query(k<<1|1,mid+1,r,max(mid+1,x),y);
        return ans;
    }
    ll query(int x)
    {
        ll ans=0;
        while(bl[x]!=1)
        {
            ans+=query(1,1,n,pos[bl[x]],pos[x]);
            x=fa[bl[x]];
        }
        ans+=query(1,1,n,1,pos[x]);
        return ans;
    }
    int main()
    {
        n=read();m=read();
        for(int i=1;i<=n;i++)v[i]=read();
        for(int i=1;i<n;i++)
        {
            int u=read(),v=read();
            insert(u,v);
        }
        dfs(1);
        dfs2(1,1);
        for(int i=1;i<=n;i++)
            add(1,1,n,pos[i],pos[i],v[i]);
        int opt,x,a;
        while(m--)
        {
            opt=read();x=read();
            if(opt==1)
            {
                a=read();add(1,1,n,pos[x],pos[x],a);
            }
            if(opt==2)
            {
                a=read();add(1,1,n,pos[x],mx[x],a);
            }
            if(opt==3)printf("%lld
    ",query(x));
        }
        return 0;
    }
    View Code

    2.【bzoj2243】[SDOI2011]染色

    给定一棵有n个节点的无根树和m个操作,操作有2类:

    1、将节点a到节点b路径上所有点都染成颜色c;

    2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”、“222”和“1”。

    请你写一个程序依次完成这m个操作。

    #include<iostream>
    #include<cstdlib>
    #include<cstdio>
    #include<cstring>
    #define N 100001
    using namespace std;
    int n,m,cnt,sz,head[N],deep[N],son[N],belong[N],pl[N],v[N],ft[N][18];
    bool vis[N];
    struct seg{int l,r,lc,rc,s,tag;}t[4*N];
    struct edge{int to,next;}e[2*N];
    void insert(int u,int v)
    {
        e[++cnt].to=v;e[cnt].next=head[u];head[u]=cnt;
        e[++cnt].to=u;e[cnt].next=head[v];head[v]=cnt;
    }
    void dfs1(int x)
    {
        vis[x]=son[x]=1;
        for(int i=1;i<=17;i++)
        {
            if(deep[x]<(1<<i))break;
            ft[x][i]=ft[ft[x][i-1]][i-1];
        }
        for(int i=head[x];i;i=e[i].next)
        {
            if(vis[e[i].to])continue;
            deep[e[i].to]=deep[x]+1;
            ft[e[i].to][0]=x;
            dfs1(e[i].to);
            son[x]+=son[e[i].to];
        }
    }
    void dfs2(int x,int chain)
    {
        pl[x]=++sz;belong[x]=chain;
        int k=0;
        for(int i=head[x];i;i=e[i].next)
            if(deep[e[i].to]>deep[x]&&son[k]<son[e[i].to])
               k=e[i].to;
        if(!k)return;
        dfs2(k,chain);
        for(int i=head[x];i;i=e[i].next)
            if(deep[e[i].to]>deep[x]&&k!=e[i].to)
               dfs2(e[i].to,e[i].to);
    }
    int lca(int x,int y)
    {
        if(deep[x]<deep[y])swap(x,y);
        int t=deep[x]-deep[y];
        for(int i=0;i<=17;i++)
           if(t&(1<<i))x=ft[x][i];
        for(int i=17;i>=0;i--)
           if(ft[x][i]!=ft[y][i])
           {x=ft[x][i];y=ft[y][i];}
        if(x==y)return x;
        return ft[x][0];
    }
    void build(int k,int l,int r)
    {
        t[k].l=l;t[k].r=r;t[k].s=1;t[k].tag=-1;
        if(l==r)return;
        int mid=(l+r)>>1;
        build(k<<1,l,mid);build(k<<1|1,mid+1,r);
    }
    void pushup(int k)
    {
        t[k].lc=t[k<<1].lc;t[k].rc=t[k<<1|1].rc;
        if(t[k<<1].rc^t[k<<1|1].lc)t[k].s=t[k<<1].s+t[k<<1|1].s;
        else t[k].s=t[k<<1].s+t[k<<1|1].s-1;
    }
    void pushdown(int k)
    {
        int tmp=t[k].tag;t[k].tag=-1;
        if(tmp==-1||t[k].l==t[k].r)return;
        t[k<<1].s=t[k<<1|1].s=1;
        t[k<<1].tag=t[k<<1|1].tag=tmp;
        t[k<<1].lc=t[k<<1].rc=tmp;
        t[k<<1|1].lc=t[k<<1|1].rc=tmp;
    }
    void change(int k,int x,int y,int c)
    {
        pushdown(k);
        int l=t[k].l,r=t[k].r;
        if(l==x&&r==y)
        {t[k].lc=t[k].rc=c;t[k].s=1;t[k].tag=c;return;}
        int mid=(l+r)>>1;
        if(mid>=y)change(k<<1,x,y,c);
        else if(mid<x)change(k<<1|1,x,y,c);
        else
        {
            change(k<<1,x,mid,c);
            change(k<<1|1,mid+1,y,c);
        }
        pushup(k);
    }
    int ask(int k,int x,int y)
    {
        pushdown(k);
        int l=t[k].l,r=t[k].r;
        if(l==x&&r==y)return t[k].s;
        int mid=(l+r)>>1;
        if(mid>=y)return ask(k<<1,x,y);
        else if(mid<x)return ask(k<<1|1,x,y);
        else
        {
            int tmp=1;
            if(t[k<<1].rc^t[k<<1|1].lc)tmp=0;
            return ask(k<<1,x,mid)+ask(k<<1|1,mid+1,y)-tmp;
        }
    }
    int getc(int k,int x)
    {
        pushdown(k);
        int l=t[k].l,r=t[k].r;
        if(l==r)return t[k].lc;
        int mid=(l+r)>>1;
        if(x<=mid)return getc(k<<1,x);
        else return getc(k<<1|1,x);
    }
    int solvesum(int x,int f)
    {
        int sum=0;
        while(belong[x]!=belong[f])
        {
            sum+=ask(1,pl[belong[x]],pl[x]);
            if(getc(1,pl[belong[x]])==getc(1,pl[ft[belong[x]][0]]))sum--;
            x=ft[belong[x]][0]; 
        }
        sum+=ask(1,pl[f],pl[x]);
        return sum;
    }
    void solvechange(int x,int f,int c)
    {
        while(belong[x]!=belong[f])
        {
            change(1,pl[belong[x]],pl[x],c);
            x=ft[belong[x]][0]; 
        }
        change(1,pl[f],pl[x],c);
    }
    void solve()
    {
        int a,b,c;
        dfs1(1);
        dfs2(1,1);
        build(1,1,n);
        for(int i=1;i<=n;i++)
            change(1,pl[i],pl[i],v[i]);
        for(int i=1;i<=m;i++)
        {
            char ch[10];
            scanf("%s",ch);
            if(ch[0]=='Q')
            {
                scanf("%d%d",&a,&b);
                int t=lca(a,b);
                printf("%d
    ",solvesum(a,t)+solvesum(b,t)-1);
            }
            else
            {
                scanf("%d%d%d",&a,&b,&c);
                int t=lca(a,b);
                solvechange(a,t,c);solvechange(b,t,c);
            }
        }
    }
    void ini()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)scanf("%d",&v[i]);
        for(int i=1;i<n;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            insert(x,y);
        }
    }
    int main()
    {
        ini();
        solve();
        return 0;
    }
    View Code

    3.【bzoj1984】月下“毛景树”

    Change k w:将第k条树枝上毛毛果的个数改变为w个。

    Cover u v w:将节点u与节点v之间的树枝上毛毛果的个数都改变为w个。

    Add u v w:将节点u与节点v之间的树枝上毛毛果的个数都增加w个。

    Max u v:询问节点u与节点v之间树枝上毛毛果个数最多有多少个。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define N 100001
    #define inf 0x7fffffff
    using namespace std;
    int n,cnt=1,sz;
    int head[N],deep[N],size[N],pos[N],belong[N];
    int fa[N][17],id[N];
    struct edge{int to,next,v;}e[N<<1];
    struct seg{int l,r,mx,a,c;}t[N<<2];
    void insert(int u,int v,int w)
    {
        e[++cnt].to=v;e[cnt].next=head[u];e[cnt].v=w;head[u]=cnt;
        e[++cnt].to=u;e[cnt].next=head[v];e[cnt].v=w;head[v]=cnt;
    }
    int lca(int x,int y)
    {
        if(deep[x]<deep[y])swap(x,y);
        int t=deep[x]-deep[y];
        for(int i=0;i<=16;i++)
           if(t&(1<<i))x=fa[x][i];
        for(int i=16;i>=0;i--)
           if(fa[x][i]!=fa[y][i])
           {x=fa[x][i];y=fa[y][i];}
        if(x==y)return x;
        return fa[x][0];
    }
    void pushdown(int k)
    {
        if(t[k].l==t[k].r)return;
        if(t[k].c!=-1)
        {
            t[k<<1].a=t[k<<1|1].a=0;
            t[k<<1].c=t[k<<1|1].c=t[k].c;
            t[k<<1].mx=t[k<<1|1].mx=t[k].c;
            t[k].c=-1;
        }
        if(t[k].a)
        {
            t[k<<1].mx+=t[k].a;t[k<<1|1].mx+=t[k].a;
            if(t[k<<1].c!=-1)t[k<<1].c+=t[k].a;
            else t[k<<1].a+=t[k].a;
            if(t[k<<1|1].c!=-1)t[k<<1|1].c+=t[k].a;
            else t[k<<1|1].a+=t[k].a;
            t[k].a=0;
        }
    }
    void build(int k,int l,int r)
    {
        t[k].l=l;t[k].r=r;t[k].c=-1;
        if(l==r)return;
        int mid=(l+r)>>1;
        build(k<<1,l,mid);build(k<<1|1,mid+1,r);
    }
    void pushup(int k)
    {t[k].mx=max(t[k<<1].mx,t[k<<1|1].mx);}
    void change(int k,int x,int y,int v)
    {
        pushdown(k);
        int l=t[k].l,r=t[k].r;
        if(l==x&&y==r){t[k].mx=t[k].c=v;return;}
        int mid=(l+r)>>1;
        if(mid>=y)change(k<<1,x,y,v);
        else if(mid<x)change(k<<1|1,x,y,v);
        else 
        {
            change(k<<1,x,mid,v);
            change(k<<1|1,mid+1,y,v);
        }
        pushup(k);
    }
    void add(int k,int x,int y,int v)
    {
        pushdown(k);
        int l=t[k].l,r=t[k].r;
        if(l==x&&y==r){t[k].mx+=v;t[k].a=v;return;}
        int mid=(l+r)>>1;
        if(mid>=y)add(k<<1,x,y,v);
        else if(mid<x)add(k<<1|1,x,y,v);
        else 
        {
            add(k<<1,x,mid,v);
            add(k<<1|1,mid+1,y,v);
        }
        pushup(k);
    }
    int ask(int k,int x,int y)
    {
        pushdown(k);
        int l=t[k].l,r=t[k].r;
        if(l==x&&y==r)return t[k].mx;
        int mid=(l+r)>>1;
        if(mid>=y)return ask(k<<1,x,y);
        else if(mid<x)return ask(k<<1|1,x,y);
        else return max(ask(k<<1,x,mid),ask(k<<1|1,mid+1,y));
    }
    void solvechange(int x,int f,int v)
    {
        while(belong[x]!=belong[f])
        {
            change(1,pos[belong[x]],pos[x],v);
            x=fa[belong[x]][0]; 
        }
        if(pos[f]+1<=pos[x])
        change(1,pos[f]+1,pos[x],v);
    }
    void solveadd(int x,int f,int v)
    {
        while(belong[x]!=belong[f])
        {
            add(1,pos[belong[x]],pos[x],v);
            x=fa[belong[x]][0]; 
        }
        if(pos[f]+1<=pos[x])
        add(1,pos[f]+1,pos[x],v);
    }
    int solveask(int x,int f)
    {
        int mx=-inf;
        while(belong[x]!=belong[f])
        {
            mx=max(mx,ask(1,pos[belong[x]],pos[x]));
            x=fa[belong[x]][0]; 
        }
        if(pos[f]+1<=pos[x])
            mx=max(mx,ask(1,pos[f]+1,pos[x]));
        return mx;
    }
    void solve()
    {
        char s[10];
        int u,v,w,f;
        while(1)
        {
            scanf("%s",s);
            switch(s[1])
            {
                case 't':return;break;
                case 'd':scanf("%d%d%d",&u,&v,&w);f=lca(u,v);
                         solveadd(u,f,w);solveadd(v,f,w);break;
                case 'o':scanf("%d%d%d",&u,&v,&w);f=lca(u,v);
                         solvechange(u,f,w);solvechange(v,f,w);
                         break;
                case 'h':scanf("%d%d",&u,&w);change(1,pos[id[u]],pos[id[u]],w);break;
                case 'a':scanf("%d%d",&u,&v);f=lca(u,v);
                         printf("%d
    ",max(solveask(u,f),solveask(v,f)));
                         break;
            }
        }
    }
    void dfs1(int x,int f)
    {
        size[x]=1;
        for(int i=1;i<=16;i++)
            if((1<<i)<=deep[x])
                fa[x][i]=fa[fa[x][i-1]][i-1];
            else break;
        for(int i=head[x];i;i=e[i].next)
        {
            if(e[i].to==f)continue;
            deep[e[i].to]=deep[x]+1;
            fa[e[i].to][0]=x;
            dfs1(e[i].to,x);
            size[x]+=size[e[i].to];
        }
    }
    void dfs2(int x,int chain)
    {
        belong[x]=chain;
        pos[x]=++sz;
        int k=0;
        for(int i=head[x];i;i=e[i].next)
        {
           if(deep[x]<deep[e[i].to])
           {
               if(size[e[i].to]>size[k])k=e[i].to;
           }
           else {id[i>>1]=x;add(1,pos[x],pos[x],e[i].v);}
        }
        if(!k)return;
        dfs2(k,chain);
        for(int i=head[x];i;i=e[i].next)
            if(deep[x]<deep[e[i].to]&&k!=e[i].to)
                dfs2(e[i].to,e[i].to);
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n-1;i++)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            insert(u,v,w);
        }
        build(1,1,n);
        dfs1(1,0);
        dfs2(1,1);
        solve();
        return 0;
    }
    View Code

    4.【bzoj3531】[Sdoi2014]旅行

    S国的居民常常旅行。旅行时他们总会走最短路,并且为了避免麻烦,只在信仰和他们相同的城市留宿。

    ”CC x c”:城市x的居民全体改信了c教;
    ”CW x w”:城市x的评级调整为w;
    ”QS x y”:一位旅行者从城市x出发,到城市y,并记下了途中留宿过的城市的评级总和;
    ”QM x y”:一位旅行者从城市x出发,到城市y,并记下了途中留宿过的城市的评级最大值。
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define M 10000005
    using namespace std;
    inline int read()
    {
        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;
    }
    int n,m,cnt,place,size;
    int s[17];
    int w[100005],c[100005],root[100005];
    int fa[100005][17],deep[100005],pl[100005],belong[100005],son[100005];
    int ls[M],rs[M],mx[M],sum[M];
    bool vis[100005];
    struct data{int to,next;}e[200005];int head[100005];
    void ins(int u,int v)
    {
        e[++cnt].to=v;e[cnt].next=head[u];head[u]=cnt;
        e[++cnt].to=u;e[cnt].next=head[v];head[v]=cnt;
    }
    //==========================================================
    void dfs1(int x)
    {
        vis[x]=1;son[x]=1;
        for(int i=1;i<=16;i++)
            if(s[i]<=deep[x])fa[x][i]=fa[fa[x][i-1]][i-1];
            else break;
        for(int i=head[x];i;i=e[i].next)
        {
            if(vis[e[i].to])continue;
            deep[e[i].to]=deep[x]+1;
            fa[e[i].to][0]=x;
            dfs1(e[i].to);
            son[x]+=son[e[i].to];
        }
    }
    void dfs2(int x,int chain)
    {
        place++;pl[x]=place;belong[x]=chain;
        int k=0;
        for(int i=head[x];i;i=e[i].next)
            if(deep[e[i].to]>deep[x]&&son[e[i].to]>son[k])
                k=e[i].to;
        if(k)dfs2(k,chain);
        for(int i=head[x];i;i=e[i].next)
            if(deep[e[i].to]>deep[x]&&e[i].to!=k)
                dfs2(e[i].to,e[i].to); 
    }
    int lca(int x,int y)
    {
        if(deep[x]<deep[y])swap(x,y);
        int t=deep[x]-deep[y];
        for(int i=0;i<=16;i++)
            if(s[i]&t)x=fa[x][i];
        for(int i=16;i>=0;i--)
            if(fa[x][i]!=fa[y][i])
                x=fa[x][i],y=fa[y][i];
        if(x==y)return x;
        return fa[x][0];
    }
    //===========================================================预处理 
    void update(int x)
    {
        mx[x]=max(mx[ls[x]],mx[rs[x]]);
        sum[x]=sum[ls[x]]+sum[rs[x]]; 
    }
    void change(int &k,int l,int r,int x,int num)
    {
        if(!k)k=++size;
        if(l==r){mx[k]=sum[k]=num;return;}
        int mid=(l+r)>>1;
        if(x<=mid)change(ls[k],l,mid,x,num);
        else change(rs[k],mid+1,r,x,num);
        update(k);
    }
    int askmx(int k,int l,int r,int x,int y)
    {
        if(!k)return 0;
        if(l==x&&y==r)return mx[k];
        int mid=(l+r)>>1;
        if(y<=mid)return askmx(ls[k],l,mid,x,y);
        else if(x>mid)return askmx(rs[k],mid+1,r,x,y);
        else return max(askmx(ls[k],l,mid,x,mid),askmx(rs[k],mid+1,r,mid+1,y));
    }
    int asksum(int k,int l,int r,int x,int y)
    {
        if(!k)return 0;
        if(l==x&&y==r)return sum[k];
        int mid=(l+r)>>1;
        if(y<=mid)return asksum(ls[k],l,mid,x,y);
        else if(x>mid)return asksum(rs[k],mid+1,r,x,y);
        else return asksum(ls[k],l,mid,x,mid)+asksum(rs[k],mid+1,r,mid+1,y);
    }
    //===========================================================线段树
    int solvemx(int c,int x,int f)
    {
        int mx=0;
        while(belong[x]!=belong[f])
        {
            mx=max(mx,askmx(root[c],1,n,pl[belong[x]],pl[x]));
            x=fa[belong[x]][0];
        }
        mx=max(mx,askmx(root[c],1,n,pl[f],pl[x]));
        return mx;
    }
    int solvesum(int c,int x,int f)
    {
        int sum=0;
        while(belong[x]!=belong[f])
        {
            sum+=asksum(root[c],1,n,pl[belong[x]],pl[x]);
            x=fa[belong[x]][0];
        }
        sum+=asksum(root[c],1,n,pl[f],pl[x]);
        return sum;
    }
    //===========================================================树链剖分 
    int main()
    {
        s[0]=1;for(int i=1;i<=16;i++)s[i]=(s[i-1]<<1);
        n=read();m=read();
        for(int i=1;i<=n;i++)
            w[i]=read(),c[i]=read();
        for(int i=1;i<n;i++)
        {
            int u=read(),v=read();
            ins(u,v);
        }
        dfs1(1);dfs2(1,1);
        for(int i=1;i<=n;i++)
            change(root[c[i]],1,n,pl[i],w[i]);
        for(int i=1;i<=m;i++)
        {
            char ch[5];scanf("%s",ch);
            int x=read(),y=read();
            if(ch[0]=='C')
            {
                if(ch[1]=='C')
                {
                    change(root[c[x]],1,n,pl[x],0);
                    c[x]=y;
                    change(root[c[x]],1,n,pl[x],w[x]);
                }
                else {change(root[c[x]],1,n,pl[x],y);w[x]=y;}
            }
            else
            {
                int f=lca(x,y);
                if(ch[1]=='S')
                {
                    int t=solvesum(c[x],x,f)+solvesum(c[x],y,f);
                    if(c[x]==c[f])t-=w[f];
                    printf("%d
    ",t);
                }
                else
                    printf("%d
    ",max(solvemx(c[x],x,f),solvemx(c[x],y,f)));
            }
        }
        return 0;
    }
    View Code

    5.【bzoj1036】[ZJOI2008]树的统计Count

    I. CHANGE u t : 把结点u的权值改为t

    II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值

    III. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define inf 0x7fffffff
    #define N 30005 
    #define M 60005
    using namespace std;
    int n,q,cnt,sz;
    int fa[N][15],v[N],deep[N],size[N],head[N];
    int pos[N],belong[N];
    bool vis[N];
    struct data{int to,next;}e[M];
    struct seg{int l,r,mx,sum;}t[100005];
    void insert(int u,int v)
    {
        e[++cnt].to=v;e[cnt].next=head[u];head[u]=cnt;
        e[++cnt].to=u;e[cnt].next=head[v];head[v]=cnt;
    }
    void ini()
    {
        scanf("%d",&n);
        for(int i=1;i<n;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            insert(x,y);
        }
        for(int i=1;i<=n;i++)scanf("%d",&v[i]);
    }
    void dfs1(int x)
    {
        size[x]=1;vis[x]=1;
        for(int i=1;i<=14;i++)
        {
            if(deep[x]<(1<<i))break;
            fa[x][i]=fa[fa[x][i-1]][i-1];//倍增处理祖先信息
        }
        for(int i=head[x];i;i=e[i].next)
        {
            if(vis[e[i].to])continue;
            deep[e[i].to]=deep[x]+1;
            fa[e[i].to][0]=x;
            dfs1(e[i].to);
            size[x]+=size[e[i].to];
        }
    }
    void dfs2(int x,int chain)
    {
        int k=0;sz++;
        pos[x]=sz;//分配x结点在线段树中的编号
        belong[x]=chain;
        for(int i=head[x];i;i=e[i].next)
            if(deep[e[i].to]>deep[x]&&size[e[i].to]>size[k])
                k=e[i].to;//选择子树最大的儿子继承重链
        if(k==0)return;
        dfs2(k,chain);
        for(int i=head[x];i;i=e[i].next)
            if(deep[e[i].to]>deep[x]&&k!=e[i].to)
                dfs2(e[i].to,e[i].to);//其余儿子新开重链
    }
    int lca(int x,int y)//求lca
    {
        if(deep[x]<deep[y])swap(x,y);
        int t=deep[x]-deep[y];
        for(int i=0;i<=14;i++)
            if(t&(1<<i))x=fa[x][i];
        for(int i=14;i>=0;i--)
            if(fa[x][i]!=fa[y][i]) 
            {x=fa[x][i];y=fa[y][i];}
        if(x==y)return x;
        else return fa[x][0];
    }
    void build(int k,int l,int r)//建线段树
    {
        t[k].l=l;t[k].r=r;
        if(l==r)return;
        int mid=(l+r)>>1;
        build(k<<1,l,mid);
        build(k<<1|1,mid+1,r);
    }
    void change(int k,int x,int y)//线段树单点修改
    {
        int l=t[k].l,r=t[k].r,mid=(l+r)>>1;
        if(l==r){t[k].sum=t[k].mx=y;return;}
        if(x<=mid)change(k<<1,x,y);
        else change(k<<1|1,x,y);
        t[k].sum=t[k<<1].sum+t[k<<1|1].sum;
        t[k].mx=max(t[k<<1].mx,t[k<<1|1].mx);
    }
    int querysum(int k,int x,int y)//线段树区间求和
    {
        int l=t[k].l,r=t[k].r,mid=(l+r)>>1;
        if(l==x&&y==r)return t[k].sum;
        if(y<=mid)return querysum(k<<1,x,y);
        else if(x>mid)return querysum(k<<1|1,x,y);
        else {return querysum(k<<1,x,mid)+querysum(k<<1|1,mid+1,y);}
    }
    int querymx(int k,int x,int y)//线段树区间求最大值
    {
        int l=t[k].l,r=t[k].r,mid=(l+r)>>1;
        if(l==x&&y==r)return t[k].mx;
        if(y<=mid)return querymx(k<<1,x,y);
        else if(x>mid)return querymx(k<<1|1,x,y);
        else {return max(querymx(k<<1,x,mid),querymx(k<<1|1,mid+1,y));}
    }
    int solvesum(int x,int f)
    {
        int sum=0;
        while(belong[x]!=belong[f])//不在一条重链上就将x跳到链首,走一条轻边,如此反复
        {
            sum+=querysum(1,pos[belong[x]],pos[x]);
            x=fa[belong[x]][0];
        }
        sum+=querysum(1,pos[f],pos[x]);
        return sum;
    }
    int solvemx(int x,int f)
    {
        int mx=-inf;
        while(belong[x]!=belong[f])
        {
            mx=max(mx,querymx(1,pos[belong[x]],pos[x]));
            x=fa[belong[x]][0];
        }
        mx=max(mx,querymx(1,pos[f],pos[x]));
        return mx;
    }
    void solve()
    {
        build(1,1,n);
        for(int i=1;i<=n;i++)
            change(1,pos[i],v[i]);
        scanf("%d",&q);char ch[6];
        for(int i=1;i<=q;i++) 
        {
            int x,y;scanf("%s%d%d",ch,&x,&y);
            if(ch[0]=='C'){v[x]=y;change(1,pos[x],y);}
            else
            {
                int t=lca(x,y);
                if(ch[1]=='M')
                    printf("%d
    ",max(solvemx(x,t),solvemx(y,t)));
                else
                    printf("%d
    ",solvesum(x,t)+solvesum(y,t)-v[t]);
            }
        }
    }
    int main()
    {
        ini();
        dfs1(1);
        dfs2(1,1);
        solve();
        return 0;
    }
    View Code

    6.【poj3237】Tree

    CHANGE i v     改变第i条边的权值为v

    NEGATE a b    a-b的边权值取反

    QUERY a b      查询a-b的最大权值

    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #define pa pair<int,int>
    #define ll long long
    #define inf 1000000000
    using namespace std;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int bin[15];
    int T,n,cnt,P;
    int last[10005];
    int bl[10005],pos[10005],to[10005];
    int fa[10005][14],size[10005],deep[10005];
    struct edge{
        int to,next,v;
    }e[20005];
    struct seg{
        int l,r,mn,mx,tag;
    }t[40005];
    void solve(int &x,int &y)
    {
        int t=x;x=-y;y=-t;
    }
    void insert(int u,int v,int w)
    {
        e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt;e[cnt].v=w;
        e[++cnt].to=u;e[cnt].next=last[v];last[v]=cnt;e[cnt].v=w;
    }
    void update(int k)
    {
        t[k].mn=min(t[k<<1].mn,t[k<<1|1].mn);
        t[k].mx=max(t[k<<1].mx,t[k<<1|1].mx);
    }
    void pushdown(int k)
    {
        int l=t[k].l,r=t[k].r;
        if(l==r||!t[k].tag)return;t[k].tag=0;
        t[k<<1].tag^=1;t[k<<1|1].tag^=1;
        solve(t[k<<1].mn,t[k<<1].mx);
        solve(t[k<<1|1].mn,t[k<<1|1].mx);
    }
    void build(int k,int l,int r)
    {
        t[k].l=l;t[k].r=r;t[k].tag=0;
        t[k].mn=inf;t[k].mx=-inf;
        if(l==r)return;
        int mid=(l+r)>>1;
        build(k<<1,l,mid);build(k<<1|1,mid+1,r);
    }
    void change(int k,int x,int val)
    {
        pushdown(k);
        int l=t[k].l,r=t[k].r,mid=(l+r)>>1;
        if(l==r)
        {
            t[k].mn=t[k].mx=val;return;
        }
        if(x<=mid)change(k<<1,x,val);
        else change(k<<1|1,x,val);
        update(k);
    }
    void rever(int k,int x,int y)
    {
        pushdown(k);
        int l=t[k].l,r=t[k].r,mid=(l+r)>>1;
        if(l==x&&r==y)
        {
            solve(t[k].mn,t[k].mx);
            t[k].tag=1;return;
        }
        if(y<=mid)rever(k<<1,x,y);
        else if(x>mid)rever(k<<1|1,x,y);
        else rever(k<<1,x,mid), rever(k<<1|1,mid+1,y);
        update(k);
    }
    int query(int k,int x,int y)
    {
        pushdown(k);
        int l=t[k].l,r=t[k].r,mid=(l+r)>>1;
        if(x==l&&y==r)return t[k].mx;
        if(y<=mid)return query(k<<1,x,y);
        else if(x>mid)return query(k<<1|1,x,y);
        else return max(query(k<<1,x,mid),query(k<<1|1,mid+1,y));
    }
    void dfs1(int x)
    {
        size[x]=1;
        for(int i=1;i<=13;i++)
            if(bin[i]<=deep[x])
                fa[x][i]=fa[fa[x][i-1]][i-1];
            else break;
        for(int i=last[x];i;i=e[i].next)
            if(e[i].to!=fa[x][0])
            {
                deep[e[i].to]=deep[x]+1;
                fa[e[i].to][0]=x;
                dfs1(e[i].to);
                size[x]+=size[e[i].to];
            }
    }
    void dfs2(int x,int chain)
    {
        bl[x]=chain;pos[x]=++P;
        int k=0;
        for(int i=last[x];i;i=e[i].next)
            if(e[i].to!=fa[x][0])
            {
                if(size[e[i].to]>size[k])k=e[i].to;
            }
            else 
            {
                to[i>>1]=pos[x];change(1,pos[x],e[i].v);
            }
        if(!k)return;
        dfs2(k,chain);
        for(int i=last[x];i;i=e[i].next)
            if(e[i].to!=fa[x][0]&&e[i].to!=k)
                dfs2(e[i].to,e[i].to);
    }
    int lca(int x,int y)
    {
        if(deep[x]<deep[y])swap(x,y);
        int t=deep[x]-deep[y];
        for(int i=0;i<=13;i++)
            if(t&bin[i])x=fa[x][i];
        for(int i=13;i>=0;i--)
            if(fa[x][i]!=fa[y][i])
                x=fa[x][i],y=fa[y][i];
        if(x==y)return x;
        return fa[x][0];
    }
    int solvequery(int x,int f)
    {
        int mx=-inf;
        while(bl[x]!=bl[f])
        {
            mx=max(mx,query(1,pos[bl[x]],pos[x]));
            x=fa[bl[x]][0];
        }
        if(pos[f]+1<=pos[x])
            mx=max(mx,query(1,pos[f]+1,pos[x]));
        return mx;
    }
    void solverever(int x,int f)
    {
        while(bl[x]!=bl[f])
        {
            rever(1,pos[bl[x]],pos[x]);
            x=fa[bl[x]][0];
        }
        if(pos[f]+1<=pos[x])
            rever(1,pos[f]+1,pos[x]);
    }
    int main()
    {
        bin[0]=1;for(int i=1;i<15;i++)bin[i]=bin[i-1]<<1;
        T=read();
        while(T--)
        {
            P=0;cnt=1;
            memset(last,0,sizeof(last));
            memset(deep,0,sizeof(deep));
            memset(fa,0,sizeof(fa));
            n=read();
            for(int i=1;i<n;i++)
            {
                int u=read(),v=read(),w=read();
                insert(u,v,w);
            }
            build(1,1,n);
            dfs1(1);
            dfs2(1,1);
            char ch[10];
            while(scanf("%s",ch+1))
            {
                if(ch[1]=='D')break;
                int x=read(),y=read();
                if(ch[1]=='Q')
                {
                    int f=lca(x,y);
                    printf("%d
    ",max(solvequery(x,f),solvequery(y,f)));
                }
                if(ch[1]=='C')
                    change(1,to[x],y);
                if(ch[1]=='N')
                {
                    int f=lca(x,y);
                    solverever(x,f);solverever(y,f);
                }
            }
        }
        return 0;
    }
    View Code

    7.Codeforces 343D Water Tree

    (1)“1 v",表示将以点v为根节点的子树全部赋值为1,

    (2)"2 v",表示将点v以及点v的所有祖先节点全部赋值为0,

    (3)"3 v",表示查询点v的值。

    //#pragma comment(linker, "/STACK:102400000,102400000")
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <vector>
    #include <algorithm>
    #include <queue>
    #include <set>
    #include <map>
    using namespace std;
    
    #define LL(x) (x<<1)
    #define RR(x) (x<<1|1)
    #define MID(a,b) (a+((b-a)>>1))
    
    const int N=500005;
    
    struct Edge
    {
        int v,pre;
        Edge(){}
        Edge(int v,int pre) :
            v(v),pre(pre) {}
    }edge[N*3];
    
    int n,m;
    int head[N],nEdge;
    int low[N],high[N],idx;
    
    void edgeInit()
    {
        nEdge=0;
        memset(head,-1,sizeof(head));
    }
    void addEdge(int u,int v)
    {
        edge[nEdge]=Edge(v,head[u]);
        head[u]=nEdge++;
    }
    
    void dfs(int u,int pre)
    {
        low[u]=++idx;
        for(int i=head[u];i!=-1;i=edge[i].pre)
        {
            int v=edge[i].v;
            if(v==pre) continue;
            dfs(v,u);
        }
        high[u]=idx;
    }
    
    struct Segtree
    {
        int delay[N*4],mx[N*4];
    
        void fun(int ind,int valu){ mx[ind]=delay[ind]=valu; }
        void PushDown(int ind)
        {
            if(delay[ind])
            {
                fun(LL(ind),delay[ind]);
                fun(RR(ind),delay[ind]);
                delay[ind]=0;
            }
        }
        void PushUp(int ind)
        {
            mx[ind]=max(mx[LL(ind)],mx[RR(ind)]);
        }
        void build(int lft,int rht,int ind)
        {
            delay[ind]=0;
            if(lft!=rht)
            {
                int mid=MID(lft,rht);
                build(lft,mid,LL(ind));
                build(mid+1,rht,RR(ind));
            }
        }
        void updata(int st,int ed,int valu,int lft,int rht,int ind)
        {
            if(st<=lft&&rht<=ed) fun(ind,valu);
            else
            {
                PushDown(ind);
                int mid=MID(lft,rht);
                if(st<=mid) updata(st,ed,valu,lft,mid,LL(ind));
                if(ed> mid) updata(st,ed,valu,mid+1,rht,RR(ind));
                PushUp(ind);
            }
        }
        int query(int st,int ed,int lft,int rht,int ind)
        {
            if(st<=lft&&rht<=ed) return mx[ind];
            else
            {
                PushDown(ind);
                int mid=MID(lft,rht);
                int mx1=0,mx2=0;
                if(st<=mid) mx1=query(st,ed,lft,mid,LL(ind));
                if(ed> mid) mx2=query(st,ed,mid+1,rht,RR(ind));
                PushUp(ind);
                return max(mx1,mx2);
            }
        }
    }seg1,seg2;
    
    int main()
    {
        while(scanf("%d",&n)!=EOF)
        {
            edgeInit(); idx=0;
            for(int i=1;i<n;i++)
            {
                int a,b; scanf("%d%d",&a,&b);
                addEdge(a,b); addEdge(b,a);
            }
    
            dfs(1,-1);
    
            seg1.build(1,idx,1); seg2.build(1,idx,1);
    
            scanf("%d",&m);
            for(int i=1;i<=m;i++)
            {
                int a,u; scanf("%d%d",&a,&u);
                if(a==1) seg1.updata(low[u],high[u],i,1,idx,1);
                else if(a==2) seg2.updata(low[u],low[u],i,1,idx,1);
                else
                {
                    int tmp1=seg1.query(low[u],low[u],1,idx,1);
                    int tmp2=seg2.query(low[u],high[u],1,idx,1);
                    if(tmp1>tmp2) puts("1");
                    else puts("0");
                }
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    算法----(1)冒泡排序
    淘宝爬虫
    爬虫_豆瓣电影top250 (正则表达式)
    爬虫_猫眼电影top100(正则表达式)
    Android 简单调用摄像头
    Android 简单天气预报
    思维模型
    This view is not constrained, it only has designtime positions, so it will jump to (0,0) unless you
    Android studio preview界面无法预览,报错render problem
    Android studio 3.1.2报错,no target device found
  • 原文地址:https://www.cnblogs.com/qscqesze/p/4593511.html
Copyright © 2011-2022 走看看