zoukankan      html  css  js  c++  java
  • jzoj6276. 【noip提高组模拟1】树

    Time Limits: 1000 ms

    Memory Limits: 524288 KB

    Description

    有一棵n个节点的无根树,给出其中的m对点对<x,y>。问有多少条树上的简单路径<u,v>满足该路径上不存在任何一对给出的点对<x,y>。
    这里我们认为路径<u,v>和<v,u>是相同的。并且对于题目中给出的点对<x,y>满足x!=y,对于你要计数的路径<u,v>满足u!=v(即单点不算答案)。

    Input

    第一行两个正整数n,m。
    接下来n-1行每行两个正整数u,v描述树上的一条边。
    接下来m行每行两个正整数x,y描述一对给出的点对。
    (注意,这里我们不保证同样的点对<x,y>不会重复出现)

    Output

    一行一个整数,表示满足要求的树上简单路径的条数。

    Sample Input

    8 3
    1 2
    1 3
    4 8
    2 4
    2 5
    3 6
    3 7
    2 3
    4 8
    6 7

    Sample Output

    11

    Data Constraint

    在这里插入图片描述

    Hint

    满足条件的路径为<1,2>,<1,3>,<1,4>,<1,5>,<1,6>,<1,7>,<2,4>,<2,5>,< 3,6>,< 3,7>,<4,5>。

    赛时

    一看到这么多的√,心想——一定可以水到巨多的分数。
    看到m=1,不是送的吗?直接拿总答案减去不合法的即可。
    看到菊花图,不是送的吗?如果不合法的限制一个是叶子,一个是根,则把叶子删掉。
    剩下的-1即可。
    看到链的情况,发现不会。
    然后又发现n和m那么小,于是稳拿70.
    最后发现,我™把调试程序交上去了!!!(调试输出的东西没删)
    然后还没发现到限制重复。
    10分妙啊♂

    题解

    部分分上面说过了,除了链的情况。
    我们发现,对于链,直观的想法——设限制为x,y,y是x的祖宗。
    那么y的祖先与x的儿子两两匹配都是不行的(显然)。
    那么我们弄出一个二维平面,x轴表示从第i个点出发,y轴表示抵达第j个点。
    这样就变成了在二维平面内有很多矩形,这些矩形内的点不能选。
    这玩意不是扫描线吗?

    即可解决,拿到90分的好成绩。

    等等,既然我们想到这里了,100分不就很显然了吗?
    我们对于数弄出dfn序,那么我们可以很轻松地处理出每个点对应的子树。
    在二维平面内搞搞即可。
    但是!如果y是x祖宗这类情况怎么办?
    很简单,求出一个y到x简单路径中距离y最近的点z。
    然后由于是dfn序,那么对于y以外的点就是除了z子树范围的其他点。
    分成两个区间即可。

    标程

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <map>
    using namespace std;
    
    struct node
    {
    	int a,b,x,y;
    };
    struct node1
    {
    	int l,r,x,k;
    };
    struct node2
    {
    	int a,lazy;
    };
    
    int q,x,y,tot,lx,ly,num,op,p,now;
    long long ans,size[100011],n;
    int tov[200011],next[200011],last[200011],fa[100011],qx[100001],qy[100001],dep[100011],rd[100011],ii[100011],st[100001],en[100001],f[100001][18];
    bool bz[201],kk[100001];
    node1 lis[800001];
    node gin[800001];
    node2 tree[800001];
    
    void joinit(int p)
    {
    	op++;lis[op].l=gin[p].x;lis[op].r=gin[p].y;lis[op].x=gin[p].a;lis[op].k=1;
    	op++;lis[op].l=gin[p].x;lis[op].r=gin[p].y;lis[op].x=gin[p].b+1;lis[op].k=-1;
    	op++;lis[op].l=gin[p].a;lis[op].r=gin[p].b;lis[op].x=gin[p].x;lis[op].k=1;
    	op++;lis[op].l=gin[p].a;lis[op].r=gin[p].b;lis[op].x=gin[p].y+1;lis[op].k=-1;
    }
    
    void make_tree(int k,int l,int r)
    {
    	tree[k].a=r-l+1;
    	tree[k].lazy=0;
    	if (l!=r)
    	{
    		int mid=(l+r)/2;
    		make_tree(k*2,l,mid);
    		make_tree(k*2+1,mid+1,r);
    	}
    }
    
    void update(int x,int l,int r)
    {
    	if (tree[x].lazy==0)
    	{
    		tree[x].a=tree[x*2].a+tree[x*2+1].a;
    		if (l==r) tree[x].a=1;
    	}
    	else
    	{
    		tree[x].a=0;
    	}
    }
    
    void change(int x,int l,int r,int st,int en,int gb)
    {
    	if (l<=en && r>=st)
    	{
    		if (l>=st && r<=en)
    		{
    			tree[x].lazy=tree[x].lazy+=gb;
    			update(x,l,r);
    		}
    		else
    		{
    			int m=(l+r)/2;
    			change(x*2,l,m,st,en,gb);
    			change(x*2+1,m+1,r,st,en,gb);
    			update(x,l,r);
    		}
    	}
    	else return;
    }
    
    void insert(int x,int y)
    {
    	tot++;
    	tov[tot]=y;
    	next[tot]=last[x];
    	last[x]=tot;
    }
    
    void dfs(int x)
    {
    	num++;
    	st[x]=num;
    	size[x]=1;
    	f[x][0]=fa[x];
    	for (ii[x]=0;ii[x]<=17;ii[x]++)
    	{
    		if (f[x][ii[x]]!=0 && f[f[x][ii[x]]][ii[x]]!=0)
    		{
    			f[x][ii[x]+1]=f[f[x][ii[x]]][ii[x]];
    		}
    		else break;
    	}
    	
    	ii[x]=last[x];
    	while (ii[x]>0)
    	{
    		if (tov[ii[x]]!=fa[x])
    		{
    			fa[tov[ii[x]]]=x;
    			dep[tov[ii[x]]]=dep[x]+1;
    			dfs(tov[ii[x]]);
    			size[x]+=size[tov[ii[x]]];
    		}
    		ii[x]=next[ii[x]];
    	} 
    	en[x]=num;
    }
    
    void qsort(int l,int r)
    {
    	int i=l;int j=r;
    	int m=qx[(i+j)/2];
    	int m1=qy[(i+j)/2];
    	while (i<=j)
    	{
    		while ((qx[i]<m) || (qx[i]==m && qy[i]>m1)) i++;
    		while ((qx[j]>m) || (qx[j]==m && qy[j]<m1)) j--;
    		if (i<=j)
    		{
    			swap(qx[i],qx[j]);
    			swap(qy[i],qy[j]);
    			i++;j--;
    		}
    	}
    	if (l<j) qsort(l,j);
    	if (r>i) qsort(i,r); 
    }
    
    void qsort1(int l,int r)
    {
    	int i=l;int j=r;
    	int m=lis[(i+j)/2].x;
    	while (i<=j)
    	{
    		while (lis[i].x<m) i++;
    		while (lis[j].x>m) j--;
    		if (i<=j)
    		{
    			swap(lis[i],lis[j]);
    			i++;j--;
    		}
    	}
    	if (l<j) qsort1(l,j);
    	if (r>i) qsort1(i,r); 
    }
    
    int get_lca(int x,int y)
    {
    	if (dep[x]<dep[y])
    	{
    		swap(x,y);	
    	}
    	int i=17;
    	while (i>=0)
    	{
    		if (dep[f[x][i]]>dep[y])
    		{
    			x=f[x][i];
    		}
    		i--;
    	}
    	if (x==y) return y;
    	else
    	{
    		for (int i=17;i>=0;i--);
    		if (f[x][i]!=f[y][i])
    		{
    			x=f[x][i];
    			y=f[y][i];
    		}
    		return f[x][0];
    	}
    }
    
    int main()
    {
    	freopen("tree.in","r",stdin);
    	freopen("tree.out","w",stdout);
    	scanf("%lld%d",&n,&q);
    	for (int i=1;i<n;i++)
    	{
    		scanf("%d%d",&x,&y);
    		insert(x,y);
    		insert(y,x);
    		rd[x]++;rd[y]++;
    	}
    	dfs(1);
    	for (int i=1;i<=q;i++)
    	{
    		scanf("%d%d",&qx[i],&qy[i]);
    	}
    	{
    		int p=0;
    		for (int i=1;i<=q;i++)
    		{
    			if (qx[i]!=qx[i-1] || qy[i]!=qy[i-1])
    			{
    				if (dep[qx[i]]<=dep[qy[i]]) swap(qx[i],qy[i]);
    				int lca=get_lca(qx[i],qy[i]);
    				if (qx[i]!=lca && qy[i]!=lca)
    				{
    					p++;gin[p].a=st[qx[i]];gin[p].x=st[qy[i]];gin[p].b=en[qx[i]];gin[p].y=en[qy[i]];
    //					printf("%d %d %d %d
    ",gin[p].a,gin[p].b,gin[p].x,gin[p].y);
    					joinit(p);
    				}
    				else
    				{
    					int k=qx[i];
    					int j=17;
    					while (j>=0)
    					{
    						if (dep[f[k][j]]>dep[qy[i]]) k=f[k][j];
    						j--;
    					}
    					p++;gin[p].a=st[qx[i]];gin[p].x=1;gin[p].b=en[qx[i]];gin[p].y=st[k]-1;
    //					printf("%d %d %d %d
    ",gin[p].a,gin[p].b,gin[p].x,gin[p].y);
    					joinit(p);
    					//if (en[k]!=n)
    					{
    						p++;gin[p].a=st[qx[i]];gin[p].x=en[k]+1;gin[p].b=en[qx[i]];gin[p].y=n;
    //						printf("%d %d %d %d
    ",gin[p].a,gin[p].b,gin[p].x,gin[p].y);
    						joinit(p);
    					}
    				}
    			}
    		}
    	}
    	make_tree(1,1,n);
    	qsort1(1,op);
    	ans=0;
    	now=1;
    	for (int i=1;i<=n;i++)
    	{
    		while (now<=op && lis[now].x==i)
    		{
    			change(1,1,n,lis[now].l,lis[now].r,lis[now].k);
    			now++;
    		}
    		ans+=tree[1].a;
    	}
    	ans-=n;
    	printf("%lld
    ",ans/2);
    }
    
    
  • 相关阅读:
    iptables
    apt
    cvc-elt.1: Cannot find the declaration of element 'beans'.
    di
    log
    java内存模型
    spring-jms
    JTS
    10java进阶——IO2
    17单例
  • 原文地址:https://www.cnblogs.com/RainbowCrown/p/11324176.html
Copyright © 2011-2022 走看看