zoukankan      html  css  js  c++  java
  • bzoj3626[LNOI2014] LCA

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3626

    题目大意:

    给出一个n个节点的有根树(编号为0到n-1,根节点为0),q个询问。求在[l,r]区间内的每个节点i与z的最近公共祖先的深度之和。

    n,q<=5,0000 答案mod 201314
    p.s.根的深度为1


    ========这是道好题 想不到再看(然而找题解的肯定都是跟我一样想不到的orz=========

    【↑这个人是zz 别管= =

    题解:

    这个好题啊..然而想了好久之后滚去看大神博客了(/v )
    ---------------------------------
    首先,如何通过路径操作求得x与y的lca的深度咧?
    -先将x到根路径上的点的权值+1,然后询问y到根路径上点的权值和,这个权值和就是x与y的lca的深度√
    而且非常好的一点就是,这个权值和是可以累加的。这是什么意思咧?
    -比如询问是[1,3]跟4的,那么分别将1,2,3到根搞一次(这个时候权值是累加的啊= =),再查询4到根上点的权值和,就得到了[1,3]分别跟4的lca的深度的和了....(感觉好废话orz)
    知道了这两个,就好做啦~
    把询问离线后排序一下,依次搞搞就好了√


    上代码 (忘了改回lld..PE了TAT)..

    啊 真的 naive的我以为加了读入优化会快很多,然而、结果、并不会= =

    那些1s-的是怎么跑的求告知!!!

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    typedef long long LL;
    #define mod 201314
    #define maxn 50100
    
    struct node
    {
    	int x,y,c,next;
    }a[maxn];
    int len,first[maxn];
    struct tree
    {
    	int l,r,lc,rc;LL c,la;//c-权值 la-lazy标志
    }tr[maxn*2];int trlen;
    struct xw
    {
    	int x,id,c;LL ans;
    	//id-存编号 最后搞原询问顺序时排序用的 x,c不造怎么描述看下面意会吧orz
    }as[maxn*2];
    int top[maxn],dep[maxn],son[maxn];
    int z=0,ys[maxn],tot[maxn],fa[maxn];
    bool cmp1(xw x,xw y) {return x.x<y.x;}
    bool cmp2(xw x,xw y) {return x.id<y.id;}
    int read()
    {
    	char ch=getchar();
        for (;ch>'9'||ch<'0';ch=getchar());
        int tmp=0;
        for (;'0'<=ch && ch<='9';ch=getchar())
          tmp=tmp*10+int(ch)-48;
        return tmp;
    }
    void ins(int x,int y)
    {
    	len++;
    	a[len].x=x;a[len].y=y;
    	a[len].next=first[x];first[x]=len;
    }
    void dfs1(int x)
    {
    	tot[x]=1;son[x]=0;
    	for (int k=first[x];k!=-1;k=a[k].next)
    	{
    		int y=a[k].y;
    		if (y!=fa[x])
    		{
    			dep[y]=dep[x]+1;
    			fa[y]=x;
    			dfs1(y);
    			if (tot[son[x]]<tot[y]) son[x]=y;
    			tot[x]+=tot[y];
    		}
    	}
    }
    void dfs2(int x,int tp)
    {
    	ys[x]=++z;top[x]=tp;
    	if (son[x]!=0) dfs2(son[x],tp);
    	for (int k=first[x];k!=-1;k=a[k].next)
    	{
    		int y=a[k].y;
    		if (y!=fa[x] && y!=son[x])
    		 dfs2(y,y);
    	}
    }
    void bt(int l,int r)
    {
    	trlen++;int now=trlen;
    	tr[now].l=l;tr[now].r=r;
    	tr[now].lc=tr[now].rc=-1;
    	tr[now].c=tr[now].la=0;
    	if (l<r)
    	{
    		int mid=(l+r)>>1;
    		tr[now].lc=trlen+1;bt(l,mid);
    		tr[now].rc=trlen+1;bt(mid+1,r);
    	}
    }
    void updata(int now,int lc,int rc)
    {
    	if (tr[now].la!=0)
    	{
    		int l=tr[lc].l,r=tr[lc].r;
    		tr[lc].c+=(r-l+1)*tr[now].la;
    		tr[lc].la+=tr[now].la;
    		l=tr[rc].l;r=tr[rc].r;
    		tr[rc].c+=(r-l+1)*tr[now].la;
    		tr[rc].la+=tr[now].la;
    		tr[now].la=0;
    	}
    }
    void change(int now,int l,int r)
    {
    	if (tr[now].l==l && tr[now].r==r)
    	{
    		tr[now].c+=r-l+1;
    		tr[now].la++;
    		return;
    	}
    	int mid=(tr[now].l+tr[now].r)>>1,lc=tr[now].lc,rc=tr[now].rc;
    	updata(now,lc,rc);
    	if (r<=mid) change(lc,l,r);
    	else if (l>mid) change(rc,l,r);
    	else change(lc,l,mid),change(rc,mid+1,r);
    	tr[now].c=tr[lc].c+tr[rc].c;
    }
    int query(int now,int l,int r)
    {
    	if (tr[now].l==l && tr[now].r==r) return tr[now].c;
    	int mid=(tr[now].l+tr[now].r)>>1,lc=tr[now].lc,rc=tr[now].rc;
    	updata(now,lc,rc);
    	if (r<=mid) return query(lc,l,r);
    	else if (l>mid) return query(rc,l,r);
    	else return query(lc,l,mid)+query(rc,mid+1,r);
    }
    void add(int x)
    {
    	int tx=top[x];
    	while (x)
    	{
    		change(1,ys[tx],ys[x]);
    		x=fa[tx];tx=top[x];
    	}
    }
    int ask(int x)
    {
    	int ans=0,tx=top[x];
    	while (x)
    	{
    		ans+=query(1,ys[tx],ys[x]);
    		x=fa[tx];tx=top[x];
    	}
    	return ans;
    }
    int main()
    {
    	//freopen("a.in","r",stdin);
    	//freopen("a.out","w",stdout);
    	int n,m,i,x,y,l,r,c,k;
    	//scanf("%d%d",&n,&m);
    	n=read();m=read();
    	len=0;memset(first,-1,sizeof(first));
    	for (i=2;i<=n;i++)
    	{
    		//scanf("%d",&x);
    		x=read();
    		x++;ins(x,i);
    	}
    	dep[1]=1;fa[1]=0;dfs1(1);
    	z=0;dfs2(1,1);
    	trlen=0;bt(1,n);
    	for (i=1;i<=m;i++)
    	{
    		//scanf("%d%d%d",&x,&y,&c);
    		x=read();y=read();c=read();
    		x++;y++;c++;
    		as[i*2-1].x=x-1;as[i*2-1].id=i*2-1;as[i*2-1].c=c;
    		as[i*2].x=y;as[i*2].id=i*2;as[i*2].c=c;
    	}sort(as+1,as+m+m+1,cmp1);
    	for (k=1,i=0;i<=n;i++)
    	{
    		add(i);
    		for (;as[k].x==i;k++)
    		  as[k].ans=ask(as[k].c);
    	}sort(as+1,as+m+m+1,cmp2);
    	for (i=1;i<=m;i++)
    		printf("%I64d
    ",(as[i*2].ans-as[i*2-1].ans)%mod);
    	return 0;
    }



  • 相关阅读:
    以相同类型的一个对象初始化另一个对象
    java之StringBuilder类详解
    java之StringBuffer类详解
    jquery在线引用地址
    java之抽象类
    Oracle动态执行表不可访问
    libvirt-qemu-TLS加密虚拟机传输实例分析
    查看系统是虚拟机还是物理机
    WorkStation 虚拟机迁移到 ESXi
    Django入门------常见问题
  • 原文地址:https://www.cnblogs.com/Euryale-Rose/p/6527869.html
Copyright © 2011-2022 走看看