题目链接:  PowerOj1179


 1179: 我要10个G

Time Limit:  8500 MS Memory Limit:  2097152 KB
Total Submit:  7 Accepted:  5 Page View:  21
Submit  Status  Discuss

    大黄对于以太网的速度要求不是一般的高,要求达到10Gbps的速度。于是上决╇ф把实验室内的网络设备全部更换成了万兆的。由于资金紧缺,上决╇ф不得不从深水宝购买这些万兆设备。后果可想而知,这些设备的的稳定性不堪入目,经常罢工。然而大黄和梁晨这小两口经常换位置。大黄想知道,每次换位置后,她和梁晨之间的网络是否通畅。


输入第一行两个正整数 n,qn,q 1n,q1051≤n,q≤105),分别代表实验室内网络设备的个数和日志条数。 接下来 n1n−1行,每行有两个正整数 u,vu,v 1u,vn1≤u,v≤n)。表示编号为 uu的设备和编号为 vv的设备之间通过一条高贵的七类屏蔽线连接。 接下来 qq行,第一个数 optopt 1opt31≤opt≤3)代表日志类别。 当 opt=1opt=1时,后面将会有两个正整数 u,vu,v 1u,vn1≤u,v≤n)。表示现在大黄的电脑连接在编号为 uu设备上,梁晨的电脑连接连接在编号为 vv的设备上。询问大黄和梁晨之间的网络是否通畅。 当 opt=2opt=2时,后面将会有一个正整数 uu 1un1≤u≤n)。表示编号为 uu的设备被上决╇ф修好了。 当 opt=3opt=3时,后面将会有一个正整数 uu 1un1≤u≤n)。表示编号为 uu的设备损坏了。 输入保证任意两台设备都是直接或间接地通过网线连通的。初始的时候,所有的网络设备都是正常工作的。并且保证不会维修一个好的设备,也不会出现已损坏的设备再次损坏的情况。
对于每一次询问日志,如果大黄和梁晨之间的网络通畅,没有损坏的设备,输出“YES”,否则“NO”
7 82 13 24 35 46 17 11 7 63 21 3 73 41 6 23 11 5 21 3 5
YESNONONONO


题目大意:


给你一颗n个节点的树和q次查询,查询为

1 u v  问u->v是否联通

2 u  将u节点修复好

3 u  u节点损坏

初始都是好的,,保证输入合法不存在修复好的节点,损坏坏的节点


题目思路:


对于树上节点区间的查询和节点的修改我们很好想到的是树链剖分,对于初始时所有节点的值为1,如果查询u->v

是否联通则u->v的距离为他们之间经过点的个数,如果不等则不联通,对于树链求点数可以先求出lca来

再根据深度算出来


AC代码:


#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
 
using namespace std;
 
const int maxn = 2e5+100;
 
/** 邻接表部分  */
 
struct st
{
    int v,nex;
}edge[maxn<<1];
 
int head[maxn],e;
 
void add(int u,int v)
{
    edge[e].v = v,edge[e].nex = head[u],head[u]=e++;
}
 
/**  树链剖分部分   */
 
int fa[maxn],dep[maxn],siz[maxn],top[maxn],son[maxn],pos[maxn],rak[maxn],val[maxn];;
int tim;
 
void dfs(int u,int pr,int d)
{
    siz[u] = 1,dep[u]=d,fa[u] = pr;
    for(int i = head[u];~i;i=edge[i].nex)
    {
        int v = edge[i].v;
        if(v==pr)continue;
        dfs(v,u,d+1);
        siz[u]+=siz[v];
        if(son[u]==-1||siz[son[u]]<siz[v])
            son[u]=v;
    }
}
 
void create(int u,int tp)
{
    top[u] = tp;
    pos[u] = ++tim;
    rak[pos[u]] = u;
    if(son[u]==-1)return ;
    create(son[u],tp);
    for(int i=head[u];~i;i=edge[i].nex)
    {
        int v = edge[i].v;
        if(v != fa[u]&&v != son[u])create(v,v);
    }
}
 
/**  线段树部分  */
 
struct nod
{
    int l,r;
    int sum,c;
}node[maxn<<3];
 
void pushdown(int rt,int m)
{
    node[rt<<1].c+=node[rt].c;
    node[rt<<1|1].c+=node[rt].c;
 
    node[rt<<1].sum+=node[rt].c*(m-m/2);
    node[rt<<1|1].sum+=node[rt].c*(m/2);
 
    node[rt].c = 0;
}
 
void pushup(int rt)
{
    node[rt].sum = node[rt<<1].sum+node[rt<<1|1].sum;
}
 
void BuildTree(int l,int r,int rt)
{
    node[rt].l = l,node[rt].r = r,node[rt].c =0;
    if(l==r)
    {
        node[rt].sum = val[rak[l]];
        return ;
    }
    int mid = (l+r)>>1;
    BuildTree(l,mid,rt<<1);
    BuildTree(mid+1,r,rt<<1|1);
    pushup(rt);
}
 
void update(int l,int r,int rt,int w)
{
    if(l<=node[rt].l&&r>=node[rt].r)
    {
        node[rt].sum+=(node[rt].r-node[rt].l+1)*w;
        node[rt].c+=w;
        return ;
    }
    if(node[rt].c)pushdown(rt,node[rt].r-node[rt].l+1);
    int mid = (node[rt].l+node[rt].r)>>1;
    if(l<=mid)update(l,r,rt<<1,w);
    if(r>mid)update(l,r,rt<<1|1,w);
    pushup(rt);
}
 
int quary(int L,int R,int l,int r,int rt)
{
    if(r<L||l>R)return 0;
    if(L<=l&&R>=r)return node[rt].sum;
    int mid = (l+r)>>1;
 
    if(node[rt].c)pushdown(rt,r-l+1);
    return quary(L,R,l,mid,rt<<1)+quary(L,R,mid+1,r,rt<<1|1);
 
}
 
/**  运行部分   */
int n,m,p;
int len;
void change(int x,int y,int w)
{
    while(top[x]!=top[y])
    {
        if(dep[top[x]]<dep[top[y]])swap(x,y);
        update(pos[top[x]],pos[x],1,w);
        x = fa[top[x]];
 
    }
    if(dep[x]>dep[y])swap(x,y);
    update(pos[x],pos[y],1,w);
}
 
int SUM(int x,int y)
{
    len = 0;   //记录点数
    int sum = 0; //记录距离
    while(top[x]!=top[y])
    {
 
        if(dep[top[x]]<dep[top[y]])swap(x,y);
        sum+=quary(pos[top[x]],pos[x],1,n,1);
        len+=abs(dep[x]-dep[fa[top[x]]]);
        x = fa[top[x]];
    }
    if(dep[x]>dep[y])swap(x,y);
    len+=dep[y]-dep[x]+1;
    sum+=quary(pos[x],pos[y],1,n,1);
    return sum;
 
}
 
void init()
{
    tim = e = 0;
    memset(head,-1,sizeof(head));
    memset(son,-1,sizeof(son));
}
 
void sove()
{
    for(int i=1;i<=n;i++)val[i] = 1;
    for(int i=1;i<n;i++)
    {
        int x,y;scanf("%d%d",&x,&y);
        add(x,y);
        add(y,x);
    }
    dfs(1,1,1);
    create(1,1);
    BuildTree(1,n,1);
    while(p--)
    {
        int s;
        int x,y,w;
        scanf("%d",&s);
        if(s==1)
        {
            scanf("%d%d",&x,&y);
            int xx = SUM(x,y);
            if(xx==len)printf("YES\n");
            else printf("NO\n");
        }
        else if(s==2)
        {
            scanf("%d",&x);
            change(x,x,1);
        }
        else
        {
            scanf("%d",&x);
            change(x,x,-1);
        }
    }
}
 
int main()
{
    scanf("%d%d",&n,&p);
    init();
    sove();
    return 0;
}