zoukankan      html  css  js  c++  java
  • bzoj 3589: 动态树【树链剖分+容斥】

    因为一开始调试不知道unsigned怎么输出就没有加 结果WA了一上午!!!!!然而最后放弃了unsigned选择了&2147483647
    首先链剖,因为它所给的链一定是某个点到根的路径上的一段(一开始没看到),也就是说链是不会拐弯的,那么考虑容斥,加上每条链的长度减去两条链的交的长度加上三条链的交的长度...
    关于求链的交,因为链不会拐弯,所以对于两条链上深度较深的两个点( (v_1,v_2) )求( lca ),如果( lca )的深度小于两条链的较浅点的任意一个,那么这两条链没有交,否则交就是( lca )到两条链的较浅点中深度交大的一个。
    然后状压枚举链的组合即可。

        if(!l||!r)
            return;
    

    这个东西去掉会( WA ),因为我把( (0,0) )这样的边没有判断也直接扔进去询问了...
    这样应该是比打标记的方法快一些,不过对于拐弯的链就只能拆开了。

    #include<iostream>
    #include<cstdio>
    using namespace std;
    const int N=200005;
    int n,q,h[N],cnt,si[N],hs[N],fa[N],de[N],fr[N],id[N],rl[N],tot;
    struct qwe
    {
        int ne,to;
    }e[N<<1];
    struct xianduanshu
    {
        int l,r,lz,sum;
    }t[N<<2];
    struct bian
    {
        int u,v;
    }a[10];
    int read()
    {
        int r=0,f=1;
        char p=getchar();
        while(p>'9'||p<'0')
        {
            if(p=='-')
                f=-1;
            p=getchar();
        }
        while(p>='0'&&p<='9')
        {
            r=r*10+p-48;
            p=getchar();
        }
        return r*f;
    }
    void add(int u,int v)
    {
        cnt++;
        e[cnt].ne=h[u];
        e[cnt].to=v;
        h[u]=cnt;
    }
    void dfs1(int u,int fat)
    {
        fa[u]=fat;
        de[u]=de[fat]+1;
        si[u]=1;
        for(int i=h[u];i;i=e[i].ne)
            if(e[i].to!=fat)
            {
                dfs1(e[i].to,u);
                si[u]+=si[e[i].to];
                if(si[e[i].to]>si[hs[u]])
                    hs[u]=e[i].to;
            }
    }
    void dfs2(int u,int top)
    {
        fr[u]=top;
        id[u]=++tot;
        rl[tot]=u;
        if(!hs[u])
            return;
        dfs2(hs[u],top);
        for(int i=h[u];i;i=e[i].ne)
            if(e[i].to!=fa[u]&&e[i].to!=hs[u])
                dfs2(e[i].to,e[i].to);
    }
    void build(int ro,int l,int r)
    {
        t[ro].l=l,t[ro].r=r;
        if(l==r)
            return;
        int mid=(l+r)>>1;
        build(ro<<1,l,mid);
        build(ro<<1|1,mid+1,r);
    }
    void pd(int ro)
    {
        t[ro<<1].sum+=t[ro].lz*(t[ro<<1].r-t[ro<<1].l+1);
        t[ro<<1].lz+=t[ro].lz;
        t[ro<<1|1].sum+=t[ro].lz*(t[ro<<1|1].r-t[ro<<1|1].l+1);
        t[ro<<1|1].lz+=t[ro].lz;
        t[ro].lz=0;
    }
    void update(int ro,int l,int r,int v)
    {
        if(!l||!r)
            return;
        if(t[ro].l==l&&t[ro].r==r)
        {
            t[ro].lz+=v;
            t[ro].sum+=v*(t[ro].r-t[ro].l+1);
            return;
        }
        pd(ro);
        int mid=(t[ro].l+t[ro].r)>>1;
        if(r<=mid)
            update(ro<<1,l,r,v);
        else if(l>mid)
            update(ro<<1|1,l,r,v);
        else
        {
            update(ro<<1,l,mid,v);
            update(ro<<1|1,mid+1,r,v);
        }
        t[ro].sum=t[ro<<1].sum+t[ro<<1|1].sum;
    }
    int ques(int ro,int l,int r)
    {
        if(!l||!r)
            return 0;
        if(t[ro].l==l&&t[ro].r==r)
            return t[ro].sum;
        pd(ro);
        int mid=(t[ro].l+t[ro].r)>>1;
        if(r<=mid)
            return ques(ro<<1,l,r);
        else if(l>mid)
            return ques(ro<<1|1,l,r);
        else
            return ques(ro<<1,l,mid)+ques(ro<<1|1,mid+1,r);
    }
    int wen(int u,int v)
    {//cout<<u<<" "<<v<<endl;
        if(!u||!v)
            return 0;
        int re=0;
        while(fr[u]!=fr[v])
        {
            if(de[fr[u]]<de[fr[v]])
                swap(u,v);
            re+=ques(1,id[fr[u]],id[u]);
            u=fa[fr[u]];
        }
        if(de[u]>de[v])
            swap(u,v);
        re+=ques(1,id[u],id[v]);
        return re;
    }
    int lca(int u,int v)
    {
        for(;fr[u]!=fr[v];de[fr[u]]>de[fr[v]]?u=fa[fr[u]]:v=fa[fr[v]]);//cout<<u<<" "<<v<<" "<<" ";if(de[u]>de[v])cout<<v;else cout<<u;cout<<endl;
        return de[u]>de[v]?v:u;
    }
    bian hb(bian a,bian b)
    {
        int lc=lca(a.v,b.v);
        bian re;
        if(de[lc]<de[a.u]||de[lc]<de[b.u])
            re.u=-1,re.v=-1;
        else
            re.u=de[a.u]>de[b.u]?a.u:b.u,re.v=lc;//cout<<a.u<<" "<<a.v<<"   "<<b.u<<" "<<b.v<<"   "<<re.u<<" "<<re.v<<endl;
        return re;
    }
    int main()
    {
        n=read();
        for(int i=1;i<n;i++)
        {
            int x=read(),y=read();
            add(x,y);add(y,x);
        }
        dfs1(1,0);//cout<<"ok"<<endl;
        dfs2(1,1);
        build(1,1,n);
        q=read();
        while(q--)
        {
            int o=read();
            if(o==0)
            {
                int u=read(),v=read();
                update(1,id[u],id[u]+si[u]-1,v);
            }
            else
            {
                int ans=0,k=read();
                for(int i=1;i<=k;i++)
                {
                    a[i].u=read(),a[i].v=read();
                    if(de[a[i].u]>de[a[i].v])
                        swap(a[i].u,a[i].v);
                }
                for(int i=1;i<(1<<k);i++)
                {
                    bian now;
                    now.u=0,now.v=0;
                    int t=-1;
                    for(int j=1;j<=k;j++)
                        if(i&(1<<(j-1)))
                        {
                            t=-t;
                            if(!now.u)
                                now=a[j];
                            else
                                now=hb(now,a[j]);
                            if(now.u==-1)
                                break;
                        }
                    if(now.u&&now.v)
                        ans+=t*wen(now.u,now.v);
                }
                printf("%d
    ",ans&2147483647);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    汇编中的String
    对于C语言可移植性的思考【转】【补充】
    AT&T Mnemonic Conventions(AT&T汇编助记法的规则)
    Macro和Procedure的比较(汇编中的宏与函数)
    File Descriptor和Sys_call number
    #include <sys/types.h>在哪里?
    IIS7 与 WCF 问题总结
    非常不错的WCF入门文章,来自Artech
    WCF 部署问题 小总结 (HTTP 不能注册的解决方法)
    IIS7 aspx出现500.21错误
  • 原文地址:https://www.cnblogs.com/lokiii/p/8227963.html
Copyright © 2011-2022 走看看