【NOIP2017提高A组模拟10.5】Ping

来源:互联网 发布:美工接单群 编辑:程序博客网 时间:2024/05/23 19:03

Description

这里写图片描述

Input
这里写图片描述

Output

这里写图片描述

Sample Input

5 4
2 1
5 3
3 1
4 3
2
2 4
3 2

Sample Output

1
2

Data Constraint

这里写图片描述

题解

这是一道比较玄学的题目
首先我们看一下在一条链怎么做,我们可以先把右端点排一下序,从左到右扫一遍,每次遇到一个左端点就把它加入到队列里面,遇到一个右端点就把整个序列清空,并且答案+1,这样很显然是对的,因为我如果再往右就覆盖不到第一个了,如果不那么右后面的一些可能又覆盖不到(那不是亏了)
然后这个结论可以拓展到树上面,可以把所有询问的lca的dfs序倒序排一下序,然后再按照顺序查找,每一次我们看一下那个询问的路径上面有没有已经删掉的点,否则我们就删掉根节点,证明和上面的都差不多
具体实现的话可以用线段树

贴代码

#include<iostream>#include<algorithm>#include<cstdio>#include<cmath>#include<cstring>#define fo(i,a,b) for(i=a;i<=b;i++)#define fo1(i,b,a) for(i=b;i>=a;i--)using namespace std;const int maxn=2e5+5;struct P{    int x,y,z,p;}a[maxn*2];int fi[maxn],ne[maxn*2],dui[maxn*2],qc[maxn],dfn[maxn],sum[maxn],de[maxn],size[maxn],ans[maxn];int tree[maxn*3];bool bz[maxn];int ff[maxn][19];int i,j,k,l,n,m,x,y,z,now,p,tot,cc;void add(int x,int y){    if (fi[x]==0) fi[x]=++now; else ne[qc[x]]=++now;    qc[x]=now; dui[now]=y;}void dfs(int x){    bz[x]=true;    int i=fi[x];    dfn[x]=++p;    size[x]=1;    while (i){        if (bz[dui[i]]==true){            i=ne[i];            continue;        }        ff[dui[i]][0]=x;        de[dui[i]]=de[x]+1;        dfs(dui[i]);        size[x]+=size[dui[i]];    }}void ge_ff(){    fo(j,1,17)        fo(i,1,n) ff[i][j]=ff[ff[i][j-1]][j-1];}int m1a(int x,int y){    if (de[x]<de[y]){        z=x; x=y; y=z;    }    int i;    fo1(i,16,0)if (de[x]-(1<<i)>=de[y]){        x=ff[x][i];    }    fo1(i,16,0)if (ff[x][i]!=ff[y][i]){        x=ff[x][i];        y=ff[y][i];    }    if (x!=y) x=ff[x][0];    return x;}int cmp(P x,P y){    return x.p>y.p;}void change(int v,int l,int r,int x){    if (l==r){        tree[v]+=z;    } else{        int mid=(l+r)/2;        if (x<=mid) change(v*2,l,mid,x); else change(v*2+1,mid+1,r,x);        tree[v]=tree[v*2]+tree[v*2+1];    }}void find(int v,int l,int r,int x,int y){    if (l==x && r==y){        tot=tot+z*tree[v];    } else{        int mid=(l+r)/2;        if (y<=mid) find(v*2,l,mid,x,y); else        if (x>mid) find(v*2+1,mid+1,r,x,y); else{            find(v*2,l,mid,x,mid);            find(v*2+1,mid+1,r,mid+1,y);        }    }}int main(){    freopen("ping.in","r",stdin);    freopen("ping.out","w",stdout);    scanf("%d%d",&n,&m);    fo(i,1,n-1){        scanf("%d%d",&x,&y);        add(x,y);        add(y,x);    }    dfs(1);    ge_ff();    scanf("%d",&m);    fo(i,1,m){        scanf("%d%d",&x,&y);        a[i].x=dfn[x]; a[i].y=dfn[y];        a[i].z=m1a(x,y);        a[i].p=dfn[a[i].z];    }    sort(a+1,a+m+1,cmp);    fo(i,1,m){        tot=0; z=1;        find(1,1,n+1,1,a[i].x);        find(1,1,n+1,1,a[i].y);        z=-1;        find(1,1,n+1,1,a[i].p);        if (!tot){            z=1; change(1,1,n+1,a[i].p);            z=-1; change(1,1,n+1,a[i].p+size[a[i].z]);            ans[++cc]=a[i].z;        }    }    printf("%d\n",cc);    fo(i,1,cc) printf("%d ",ans[i]);    return 0;}
阅读全文
0 0
原创粉丝点击