• bzoj4448: [Scoi2015]情报传递


    一眼上去,嗯,这题主席树,码量太大了周末再做。

    今天,诶好像还要树剖?

    对于每一条重链,用主席树维护,主席树建立权值线段树,求区间的值的个数。

    发现是在线修改(冒汗我忘了主席树怎么这样搞)

    然后Rose说离线就可以了。(机智)

    然后飞快的码,调了调数据。结果第一次T掉了,要数据,调不出来,被肉丝和星感大神联合D飞,树剖模版打错了。。。

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    
    struct node
    {
        int x,y,next;
    }a[210000];int len,last[210000];
    void ins(int x,int y)
    {
        len++;
        a[len].x=x;a[len].y=y;
        a[len].next=last[x];last[x]=len;
    }
    
    int fa[210000],son[210000],tot[210000],dep[210000];
    void pre_tree_node(int x)
    {
        tot[x]=1;son[x]=0;
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            dep[y]=dep[x]+1;
            pre_tree_node(y);
            if(tot[y]>tot[son[x]])son[x]=y;
            tot[x]+=tot[y];
        }
    }
    int z,ys[210000],tp[210000];
    void pre_tree_edge(int x,int t)
    {
        ys[x]=++z;tp[x]=t;
        if(son[x]!=0)pre_tree_edge(son[x],t);
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(y!=son[x])pre_tree_edge(y,y);
        }
    }
    
    //----------composition-------------- 
    
    struct chairmantree
    {
        int lc,rc,c;
    }tr[4100000];int trlen,rt[210000];
    int maketree(int now,int l,int r,int p)
    {
        if(now==0)now=++trlen;
        tr[now].c++;
        if(l<r)
        {
            int mid=(l+r)/2;
            if(p<=mid)tr[now].lc=maketree(tr[now].lc,l,mid,p);
            else       tr[now].rc=maketree(tr[now].rc,mid+1,r,p);
        }
        return now;
    }
    int merge(int x,int y)
    {
        if(x==0||y==0)return x+y;
        tr[x].c+=tr[y].c;
        tr[x].lc=merge(tr[x].lc,tr[y].lc);
        tr[x].rc=merge(tr[x].rc,tr[y].rc);
        return x;
    }
    int getsum(int x,int y,int l,int r,int ll,int rr)
    {
        if(x==0&&y==0)return 0;
        if(l==ll&&r==rr)return tr[y].c-tr[x].c;
        int mid=(l+r)/2;
               if(rr<=mid)return getsum(tr[x].lc,tr[y].lc,l,mid,ll,rr);
        else if(mid+1<=ll)return getsum(tr[x].rc,tr[y].rc,mid+1,r,ll,rr);
        else return getsum(tr[x].lc,tr[y].lc,l,mid,ll,mid)+getsum(tr[x].rc,tr[y].rc,mid+1,r,mid+1,rr);
    }
    
    //-------------chairmantree------------
    
    int n;
    int solve(int x,int y,int c)
    {
        int sum=0,ans=0;
        int tx=tp[x],ty=tp[y];
        while(tx!=ty)
        {
            if(dep[tx]>dep[ty]){swap(x,y);swap(tx,ty);}
            if(c>=1)ans+=getsum(rt[ys[ty]-1],rt[ys[y]],1,n,1,c);
            sum+=dep[y]-dep[ty]+1;
            y=fa[ty];ty=tp[y];
        }
        
        if(dep[x]>dep[y])swap(x,y);
        if(c>=1)ans+=getsum(rt[ys[x]-1],rt[ys[y]],1,n,1,c);
        sum+=dep[y]-dep[x]+1;
        printf("%d %d
    ",sum,ans);
    }
    
    struct change
    {
        int x,c;
    }C[210000];int clen;
    bool cmp(change n1,change n2){return ys[n1.x]<ys[n2.x];}
    struct query
    {
        int x,y,c;
    }q[210000];int qlen;
    int main()
    {
    //    freopen("message.in","r",stdin);
    //    freopen("message.out","w",stdout);
        scanf("%d",&n);
        len=0;memset(last,0,sizeof(last));
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&fa[i]);
            if(fa[i]!=0)ins(fa[i],i);
        }
        dep[1]=1;pre_tree_node(1);
        z=0;pre_tree_edge(1,1);
        
        trlen=0;memset(rt,0,sizeof(rt));
        int m,op,x,y,c;
        scanf("%d",&m);qlen=0;clen=0;
        for(int i=1;i<=m;i++)
        {
            scanf("%d",&op);
            if(op==1)
            {
                scanf("%d%d%d",&x,&y,&c);
                qlen++;q[qlen].x=x;q[qlen].y=y;q[qlen].c=i-c-1;
            }
            else
            {
                scanf("%d",&x);
                clen++;C[clen].x=x;C[clen].c=i;
            }
        }
        sort(C+1,C+clen+1,cmp);
        int ctip=1;
        for(int i=1;i<=z;i++)
        {
            if(i==ys[C[ctip].x])
            {
                rt[i]=maketree(rt[i],1,n,C[ctip].c);
                ctip++;
            }
            else {rt[i]=++trlen;tr[trlen].c=0;}
            rt[i]=merge(rt[i],rt[i-1]);
        }
        for(int i=1;i<=qlen;i++)
            solve(q[i].x,q[i].y,q[i].c);
        return 0;
    }
  • 相关阅读:
    利用SuperMap Deskpro进行Peking 54到WGS84的转换
    远程序列化xml文件(可用于自动更新程序中版本号的比较,更新文件的读取等)
    [转]C#导出到EXCEL
    [转]常用数学公式
    CLR Via C#系列学习笔记之委托
    黑马程序员C#语言中的三种循环:while 循环、dowhile 循环、for 循环。
    .net2005中GridView或者Datalist等超級流行的分頁
    Array.splice()删除数组中重复的数据
    .net中常需对文件夹以及常用的操作方法
    文件的上传下载示例
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/8595988.html
Copyright © 2020-2023  润新知