zoukankan      html  css  js  c++  java
  • QTREE[不定期更新]

      我又开新坑啦:QTREE系列.

      刚开始以为QTREE就是LCT,然后发现第一题是个树链剖分,于是以为QTREE就是树链剖分.写完后发现第二题是个树上倍增.

      综上,QTREE就是树上询问的一些题.

      来源:http://172.20.6.3/Categories.asp?page=11&order=ASC&channel=ID&c=8

      

    #include<iostream>
    #include<iomanip>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<string>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<stack>
    #include<queue>
    #include<deque>
    #include<set>
    #include<bitset>
    using namespace std;
    char buf[1<<15],*fs,*ft;
    inline char getc(){
      return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:* fs++;
    }
    inline int read(){
        int This=0,F=1; char ch=getc();
        while(ch<'0'||ch>'9'){
            if(ch=='-') F=-1;
            ch=getc();
        }
        while(ch>='0'&&ch<='9'){
            This=(This<<1)+(This<<3)+ch-'0';
            ch=getc();
        }
        return This*F;
    }
    
    inline void write(int x){
        if(x==0){
            putchar('0');
            return;
        }
        if(x<0){
            putchar('-');
            x=-x;
        }
        int num=0;char ch[16];
        while(x) ch[++num]=x%10+'0',x/=10;
        while(num) putchar(ch[num--]);
    }
    
    int siz[10010],top[10010],son[10010],fa[10010],dfn[10010],tot,head[10010],d[10010],fav[10010];
    int n,maxx[40010];
    struct edge
    {
        int x,y,next,v;
    }e[30000],o[10010];
    inline void add(int x,int y,int v)
    {
        tot++;
        e[tot]=(edge){x,y,head[x],v};
        head[x]=tot;
    }
    inline void change(int now,int l,int r,int x,int v)
    {
        if(l==r)
        {    
            maxx[now]=v;
            return ;
        }
        int mid=l+r>>1;
        if(x<=mid)
            change(now<<1,l,mid,x,v);
        else 
            change(now<<1|1,mid+1,r,x,v);
        maxx[now]=max(maxx[now<<1],maxx[now<<1|1]);
    }
    inline void dfs1(int x)
    {
        siz[x]=1;
        for(int i=head[x];i;i=e[i].next)
        {
            if(e[i].y==fa[x])
                continue;
            d[e[i].y]=d[x]+1;
            fa[e[i].y]=x;
            dfs1(e[i].y);
            siz[x]+=siz[e[i].y];
            if(siz[e[i].y]>siz[son[x]])
                son[x]=e[i].y;
        }
    }
    inline void dfs2(int x)
    {
        tot++;
        dfn[x]=tot;
        if(!son[x])
            return ;
        top[son[x]]=top[x];
        dfs2(son[x]);
        for(int i=head[x];i;i=e[i].next)
        {
            if(e[i].y==fa[x])
                continue;
            else if(e[i].y==son[x])
                change(1,1,n,dfn[son[x]],e[i].v);
            else 
            {
                top[e[i].y]=e[i].y;
                fav[e[i].y]=e[i].v;
                dfs2(e[i].y);
            }
        }
        
    }
    inline int ask(int now,int l,int r,int tl,int tr)
    {
        if(tl<=l&&r<=tr)
            return maxx[now];
        int mid=l+r>>1,ans=0;
        if(tl<=mid)
            ans=max(ans,ask(now<<1,l,mid,tl,tr));
        if(tr>mid)
            ans=max(ans,ask(now<<1|1,mid+1,r,tl,tr));
        return ans;
    }
    inline int query(int x,int y)
    {
        if(x==y)
            return 0;
        int fx=top[x],fy=top[y],ans=0;
        while(fx!=fy)
        {
            if(d[fx]>=d[fy])
            {
                ans=max(ans,ask(1,1,n,dfn[fx]+1,dfn[x]));
                ans=max(ans,fav[fx]);
                x=fa[fx];
                fx=top[x];
            }
            else 
            {
                ans=max(ans,ask(1,1,n,dfn[fy]+1,dfn[y]));
                ans=max(ans,fav[fy]);
                y=fa[fy];
                fy=top[y];
            }
        }
        if(x!=y)
        {
            if(d[x]<d[y])
                ans=max(ans,ask(1,1,n,dfn[x]+1,dfn[y]));
            else 
                ans=max(ans,ask(1,1,n,dfn[y]+1,dfn[x]));
        }
        return ans;
        
    }
    inline void gai(int nod,int v)
    {
        int x=o[nod].x,y=o[nod].y;
        if(d[x]>d[y])
            swap(x,y);
        if(son[x]==y)
            change(1,1,n,dfn[y],v);
        else 
            fav[y]=v;
    }
    inline void check(int now,int l,int r)
    {
        cout<<l<<' '<<r<<' '<<maxx[now]<<endl;
        if(l==r)
            return ;
        int mid=l+r>>1;
        check(now<<1,l,mid);
        check(now<<1|1,mid+1,r);
    }
    int main()
    {
        //freopen("123.in","r",stdin);
        //freopen("123.out","w",stdout);
        int __size__ = 20 << 20; // 20MB
        char *__p__ = (char*)malloc(__size__) + __size__;
        __asm__("movl %0, %%esp
    " :: "r"(__p__));
        for(int T=read();T;T--)
        {
            n=read();
            memset(head,0,sizeof(head));
            memset(siz,0,sizeof(siz));
            memset(top,0,sizeof(top));
            memset(son,0,sizeof(son));
            memset(fa,0,sizeof(fa));
            memset(dfn,0,sizeof(dfn));
            memset(d,0,sizeof(d));
            memset(fav,0,sizeof(fav));
            memset(maxx,0,sizeof(maxx));
            tot=0;
            for(int i=1;i<n;i++)
            {
                o[i].x=read();o[i].y=read();int w=read();
                add(o[i].x,o[i].y,w);
                add(o[i].y,o[i].x,w);
            }
            tot=0;
            dfs1(1);
            top[1]=1;
            dfs2(1);
            while(1)
            {
                char ch=getc();
                while(ch!='Q'&&ch!='C'&&ch!='D')
                    ch=getc();
                if(ch=='Q')
                {
                    int tx=read();int ty=read();
                    cout<<query(tx,ty)<<endl;
                }
                else if(ch=='C')
                {
                    int tot=read();int tv=read();
                    gai(tot,tv);
                }
                else 
                    break;
            }
        }/*
        for(int i=1;i<=n;i++)
        {
            cout<<i<<' '<<fav[i]<<endl;
        }*/
        //check(1,1,n);
    }
    p2047
    #include<iostream>
    #include<iomanip>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<string>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<stack>
    #include<queue>
    #include<deque>
    #include<set>
    #include<bitset>
    using namespace std;
    char buf[1<<15],*fs,*ft;
    inline char getc(){
      return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:* fs++;
    }
    inline int read(){
        int This=0,F=1; char ch=getc();
        while(ch<'0'||ch>'9'){
            if(ch=='-') F=-1;
            ch=getc();
        }
        while(ch>='0'&&ch<='9'){
            This=(This<<1)+(This<<3)+ch-'0';
            ch=getc();
        }
        return This*F;
    }
    
    inline void write(int x){
        if(x==0){
            putchar('0');
            return;
        }
        if(x<0){
            putchar('-');
            x=-x;
        }
        int num=0;char ch[16];
        while(x) ch[++num]=x%10+'0',x/=10;
        while(num) putchar(ch[num--]);
    }
    int n,d[10010],fa[10010][20],c[10010][20],head[10010],tot;
    struct edge
    {
        int y,next,v;
    }e[20010];
    inline void add(int x,int y,int v)
    {
        tot++;
        e[tot]=(edge){y,head[x],v};
        head[x]=tot;
    }
    inline int get_sum(int x,int y)
    {
        int sum=0;
        if(d[x]>d[y])
            swap(x,y);
        for(int t=15;t>=0;t--)
        {
            if(d[fa[y][t]]>=d[x])
                sum+=c[y][t],y=fa[y][t];
        }
        if(x==y)
            return sum;
        for(int t=15;t>=0;t--)
        {
            if(fa[x][t]!=fa[y][t])
                sum+=c[x][t]+c[y][t],x=fa[x][t],y=fa[y][t];
        }
        return sum+c[x][0]+c[y][0];
    }
    inline int get_lca(int x,int y)
    {
        if(d[x]>d[y])
            swap(x,y);
        for(int t=15;t>=0;t--)
        {
            if(d[fa[y][t]]>=d[x])
                y=fa[y][t];
        }
        if(x==y)
            return x;
        for(int t=15;t>=0;t--)
        {
            if(fa[x][t]!=fa[y][t])
                x=fa[x][t],y=fa[y][t];
        }
        return fa[x][0];
    }
    
    inline int get_by_k(int x,int k)
    {
        for(int t=15;t>=0;t--)
        {
            if((1<<t)<=k)
                x=fa[x][t],k-=(1<<t);
        }
        return x;
    }
    stack<int>q;
    int main()
    {
        //freopen("123.in","r",stdin);
        //freopen("123.out","w",stdout);
        for(int T=read();T;T--)
        {
            memset(d,0,sizeof(d));
            memset(head,0,sizeof(head));
            tot=0;
            //fa,c
            n=read();
            for(int i=1;i<n;i++)
            {
                int tx=read(),ty=read(),tv=read();
                add(tx,ty,tv);
                add(ty,tx,tv);
            }
            q.push(1);d[1]=1;
            while(q.size())
            {
                int x=q.top();q.pop();
                for(int i=head[x];i;i=e[i].next)
                {
                    if(d[e[i].y])
                        continue;
                    d[e[i].y]=d[x]+1;
                    fa[e[i].y][0]=x;
                    c[e[i].y][0]=e[i].v;
                    q.push(e[i].y);
                }
            }
            for(int t=1;t<=15;t++)
            {
                for(int i=1;i<=n;i++)
                {
                    fa[i][t]=fa[fa[i][t-1]][t-1];
                    c[i][t]=c[i][t-1]+c[fa[i][t-1]][t-1];
                }
            }
            while(1)
            {
                char ch=getc();
                while(ch!='D'&&ch!='K')
                    ch=getc();
                if(ch=='D')
                {
                    ch=getc();
                    if(ch=='I')
                        cout<<get_sum(read(),read())<<endl;
                    else 
                        break;
                }
                else 
                {
                    int x=read();int y=read();int k=read();
                    int lca=get_lca(x,y);
                    if(d[x]-d[lca]+1>=k)
                        cout<<get_by_k(x,k-1);
                    else 
                        cout<<get_by_k(y,d[y]+d[x]-d[lca]-k+1-d[lca]);
                    cout<<endl;
                }
            }
        }
    }
    p2048
    #include<iostream>
    #include<iomanip>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<string>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<stack>
    #include<queue>
    #include<deque>
    #include<set>
    #include<bitset>
    using namespace std;
    char buf[1<<15],*fs,*ft;
    inline char getc(){
      return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:* fs++;
    }
    inline int read(){
        int This=0,F=1; char ch=getc();
        while(ch<'0'||ch>'9'){
            if(ch=='-') F=-1;
            ch=getc();
        }
        while(ch>='0'&&ch<='9'){
            This=(This<<1)+(This<<3)+ch-'0';
            ch=getc();
        }
        return This*F;
    }
    
    inline void write(int x){
        if(x==0){
            putchar('0');
            return;
        }
        if(x<0){
            putchar('-');
            x=-x;
        }
        int num=0;char ch[16];
        while(x) ch[++num]=x%10+'0',x/=10;
        while(num) putchar(ch[num--]);
    }
    int n,head[100010],tot,dfn[100010],top[100010],fa[100010],siz[100010],son[100010],a[400010],num[100010];
    struct edge
    {
        int y,next;
    }e[200010];
    void add(int x,int y)
    {
        tot++;
        e[tot]=(edge){y,head[x]};
        head[x]=tot;
    }
    void dfs1(int x)
    {
        siz[x]=1;
        for(int i=head[x];i;i=e[i].next)
        {
            if(e[i].y==fa[x])
                continue;
            //d[e[i].y]=d[x]+1;
            fa[e[i].y]=x;
            dfs1(e[i].y);
            siz[x]+=siz[e[i].y];
            if(siz[e[i].y]>siz[son[x]])
                son[x]=e[i].y;
        }
    }
    void dfs2(int x)
    {
        tot++;
        dfn[x]=tot;
        num[tot]=x;
        if(!son[x])
            return ;
        top[son[x]]=top[x];
        dfs2(son[x]);
        for(int i=head[x];i;i=e[i].next)
        {
            if(e[i].y==fa[x]||e[i].y==son[x])continue;
            top[e[i].y]=e[i].y;
            dfs2(e[i].y);
        }
    }
    int ask(int now,int l,int r,int tl,int tr)
    {
        if(tl<=l&&r<=tr)
            return a[now];
        int mid=l+r>>1,t=0;
        if(tl<=mid)
        {
            t=ask(now<<1,l,mid,tl,tr);
            if(t)
                return t;
        }
        if(tr>mid)
            return ask(now<<1|1,mid+1,r,tl,tr);
        else 
            return 0;
    }
    int query(int x)
    {
        int fx=top[x],ans=0,t=0;
        while(fx!=1)
        {
            t=ask(1,1,n,dfn[fx],dfn[x]);
            if(t)//一旦有,那就是
                ans=t;
            x=fa[fx];
            fx=top[x];
        }
        t=ask(1,1,n,dfn[1],dfn[x]);
        if(t)
            return t;
        else 
            return ans;
    }
    void change(int now,int l,int r,int x)
    {
        if(l==r)
        {
            a[now]=x-a[now];
    
            return ;
        }
        int mid=l+r>>1;
        if(x<=mid)
            change(now<<1,l,mid,x);
        else 
            change(now<<1|1,mid+1,r,x);
        a[now]=a[now<<1]?a[now<<1]:a[now<<1|1];
    }/*
    void check(int now,int l,int r)
    {
        cout<<l<<' '<<r<<' '<<a[now]<<endl;
        if(l==r)
            return ;
        int mid=l+r>>1;
        check(now<<1,l,mid);
        check(now<<1|1,mid+1,r);
    }*/
    
    int main()
    {
        //freopen("123.in","r",stdin);
        n=read();int Q=read();
        for(int i=1;i<n;i++)
        {
            int tx=read();int ty=read();
            add(tx,ty);
            add(ty,tx);
        }
        num[0]=-1;
        tot=0;
        dfs1(1);
        top[1]=1;
        dfs2(1);
        for(;Q;Q--)
        {
            if(read())
            {
                write(num[query(read())]);
                putchar(10);
            }
            else 
            {
                change(1,1,n,dfn[read()]);
            }
        }
    }
    p2049

      p2047

      简单的树链剖分.

      两遍dfs剖一下.用线段树维护树链上最粗的枝干,每个树链的top再记录自己到父亲的那条边.每次修改就单点修改,查询就边跳边取max.

      应该用不着记录"每个树链的top到父亲的那条边",这样看起来很不简洁,应该是我写的太糙了.


      p2048

      既然没有修改操作,为什么不用树上倍增水过呢?
      记录每个点的2^k的祖先和到达那个祖先的路径长度.

      查询操作大体上和求lca很相似了.两点路径长就边跳边+=,求x到y的路径上第k个结点有一点点麻烦.先求出lca,这样就可以通过d[]数组得到lca和x之间有几个点.如果在lca和x的路径上就从x往上跳k-1次,否则从y往上跳d[y]+d[x]-2*d[lca]-k+1次.


      p2049

      继续树链剖分.

      dfn[i]表示编号为i的花的dfs序,num[i]表示dfs序为i的花的编号.

      用线段树维护链上第一个出现红花的时间戳(dfn),显然只需要贪心一下.

      操作一可以单点修改,操作二边取min边往上跳.最后在num里找到编号即可.

  • 相关阅读:
    插入排序
    dojo树的节点添加链接的例子
    Discuz 3x 配置问题
    mysql_connect() 不支持 请检查 mysql 模块是否正确加载
    IIS访问php页面问题,报告404错误
    Map使用操作系统内存的情况
    IT级别
    java类型和mysql类型的转换
    C++析构函数的自动调用问题
    c++中虚函数
  • 原文地址:https://www.cnblogs.com/qywyt/p/10537405.html
Copyright © 2011-2022 走看看